Finish off bug 680, allowing targets to custom lower frame and return

address nodes.

llvm-svn: 33636
This commit is contained in:
Nate Begeman 2007-01-29 22:58:52 +00:00
parent e3b09fbbb0
commit eda5997cc8
13 changed files with 69 additions and 66 deletions

View File

@ -84,6 +84,13 @@ namespace ISD {
// The address of the GOT
GLOBAL_OFFSET_TABLE,
// FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and
// llvm.returnaddress on the DAG. These nodes take one operand, the index
// of the frame or return address to return. An index of zero corresponds
// to the current function's frame or return address, an index of one to the
// parent's frame or return address, and so on.
FRAMEADDR, RETURNADDR,
// TargetConstant* - Like Constant*, but the DAG does not do any folding or
// simplification of the constant.

View File

@ -739,14 +739,6 @@ public:
bool isVarArg, unsigned CallingConv, bool isTailCall,
SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
/// LowerFrameReturnAddress - This hook lowers a call to llvm.returnaddress or
/// llvm.frameaddress (depending on the value of the first argument). The
/// return values are the result pointer and the resultant token chain. If
/// not implemented, both of these intrinsics will return null.
virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG);
/// LowerOperation - This callback is invoked for operations that are
/// unsupported by the target, which are registered to use 'custom' lowering,
/// and whose defined values are all legal.

View File

@ -652,6 +652,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break;
}
break;
case ISD::FRAMEADDR:
case ISD::RETURNADDR:
// The only option for these nodes is to custom lower them. If the target
// does not custom lower them, then return zero.
Tmp1 = TLI.LowerOperation(Op, DAG);
if (Tmp1.Val)
Result = Tmp1;
else
Result = DAG.getConstant(0, TLI.getPointerTy());
break;
case ISD::AssertSext:
case ISD::AssertZext:
Tmp1 = LegalizeOp(Node->getOperand(0));

View File

@ -2665,6 +2665,8 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::FrameIndex: return "FrameIndex";
case ISD::JumpTable: return "JumpTable";
case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE";
case ISD::RETURNADDR: return "RETURNADDR";
case ISD::FRAMEADDR: return "FRAMEADDR";
case ISD::ConstantPool: return "ConstantPool";
case ISD::ExternalSymbol: return "ExternalSymbol";
case ISD::INTRINSIC_WO_CHAIN: {

View File

@ -570,7 +570,6 @@ public:
void visitVAArg(VAArgInst &I);
void visitVAEnd(CallInst &I);
void visitVACopy(CallInst &I);
void visitFrameReturnAddress(CallInst &I, bool isFrameAddress);
void visitMemIntrinsic(CallInst &I, unsigned Op);
@ -1932,8 +1931,14 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
case Intrinsic::vastart: visitVAStart(I); return 0;
case Intrinsic::vaend: visitVAEnd(I); return 0;
case Intrinsic::vacopy: visitVACopy(I); return 0;
case Intrinsic::returnaddress: visitFrameReturnAddress(I, false); return 0;
case Intrinsic::frameaddress: visitFrameReturnAddress(I, true); return 0;
case Intrinsic::returnaddress:
setValue(&I, DAG.getNode(ISD::RETURNADDR, TLI.getPointerTy(),
getValue(I.getOperand(1))));
return 0;
case Intrinsic::frameaddress:
setValue(&I, DAG.getNode(ISD::FRAMEADDR, TLI.getPointerTy(),
getValue(I.getOperand(1))));
return 0;
case Intrinsic::setjmp:
return "_setjmp"+!TLI.usesUnderscoreSetJmp();
break;
@ -3207,19 +3212,6 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
return std::make_pair(ResVal, Res.getValue(Res.Val->getNumValues()-1));
}
// It is always conservatively correct for llvm.returnaddress and
// llvm.frameaddress to return 0.
//
// FIXME: Change this to insert a FRAMEADDR/RETURNADDR node, and have that be
// expanded to 0 if the target wants.
std::pair<SDOperand, SDOperand>
TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain,
unsigned Depth, SelectionDAG &DAG) {
return std::make_pair(DAG.getConstant(0, getPointerTy()), Chain);
}
SDOperand TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
assert(0 && "LowerOperation not implemented for this target!");
abort();
@ -3233,14 +3225,6 @@ SDOperand TargetLowering::CustomPromoteOperation(SDOperand Op,
return SDOperand();
}
void SelectionDAGLowering::visitFrameReturnAddress(CallInst &I, bool isFrame) {
unsigned Depth = (unsigned)cast<ConstantInt>(I.getOperand(1))->getZExtValue();
std::pair<SDOperand,SDOperand> Result =
TLI.LowerFrameReturnAddress(isFrame, getRoot(), Depth, DAG);
setValue(&I, Result.first);
DAG.setRoot(Result.second);
}
/// getMemsetValue - Vectorized representation of the memset value
/// operand.
static SDOperand getMemsetValue(SDOperand Value, MVT::ValueType VT,

View File

@ -1130,7 +1130,10 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
case ISD::SRA: return LowerSRx(Op, DAG, Subtarget);
case ISD::FORMAL_ARGUMENTS:
return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::RETURNADDR: break;
case ISD::FRAMEADDR: break;
}
return SDOperand();
}
//===----------------------------------------------------------------------===//

View File

@ -544,6 +544,9 @@ SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
return DAG.getTruncStore(S1, DAG.getConstant(VarArgsOffset, MVT::i64),
SA2, NULL, 0, MVT::i32);
}
// Frame & Return address. Currently unimplemented
case ISD::RETURNADDR: break;
case ISD::FRAMEADDR: break;
}
return SDOperand();

View File

@ -532,13 +532,6 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
return std::make_pair(RetVal, Chain);
}
std::pair<SDOperand, SDOperand> IA64TargetLowering::
LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG) {
assert(0 && "LowerFrameReturnAddress unimplemented");
abort();
}
SDOperand IA64TargetLowering::
LowerOperation(SDOperand Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) {
@ -594,5 +587,9 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
return DAG.getStore(Op.getOperand(0), FR,
Op.getOperand(1), SV->getValue(), SV->getOffset());
}
// Frame & Return address. Currently unimplemented
case ISD::RETURNADDR: break;
case ISD::FRAMEADDR: break;
}
return SDOperand();
}

View File

@ -66,10 +66,6 @@ namespace llvm {
/// (currently, only "ret void")
virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG);
// XXX virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI,
// XXX MachineBasicBlock *MBB);
};

View File

@ -2634,6 +2634,10 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
case ISD::SCALAR_TO_VECTOR: return LowerSCALAR_TO_VECTOR(Op, DAG);
case ISD::MUL: return LowerMUL(Op, DAG);
// Frame & Return address. Currently unimplemented
case ISD::RETURNADDR: break;
case ISD::FRAMEADDR: break;
}
return SDOperand();
}

View File

@ -868,7 +868,11 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
}
return DAG.getNode(SPISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
}
// Frame & Return address. Currently unimplemented
case ISD::RETURNADDR: break;
case ISD::FRAMEADDR: break;
}
return SDOperand();
}
MachineBasicBlock *

View File

@ -1940,25 +1940,6 @@ SDOperand X86TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) {
std::pair<SDOperand, SDOperand> X86TargetLowering::
LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG) {
SDOperand Result;
if (Depth) // Depths > 0 not supported yet!
Result = DAG.getConstant(0, getPointerTy());
else {
SDOperand RetAddrFI = getReturnAddressFrameIndex(DAG);
if (!isFrameAddress)
// Just load the return address
Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), RetAddrFI,
NULL, 0);
else
Result = DAG.getNode(ISD::SUB, getPointerTy(), RetAddrFI,
DAG.getConstant(4, getPointerTy()));
}
return std::make_pair(Result, Chain);
}
/// translateX86CC - do a one to one translation of a ISD::CondCode to the X86
/// specific condition code. It returns a false if it cannot do a direct
/// translation. X86CC is the translated CondCode. LHS/RHS are modified as
@ -4621,6 +4602,26 @@ X86TargetLowering::LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
}
}
SDOperand X86TargetLowering::LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG) {
// Depths > 0 not supported yet!
if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0)
return SDOperand();
// Just load the return address
SDOperand RetAddrFI = getReturnAddressFrameIndex(DAG);
return DAG.getLoad(getPointerTy(), DAG.getEntryNode(), RetAddrFI, NULL, 0);
}
SDOperand X86TargetLowering::LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG) {
// Depths > 0 not supported yet!
if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0)
return SDOperand();
SDOperand RetAddrFI = getReturnAddressFrameIndex(DAG);
return DAG.getNode(ISD::SUB, getPointerTy(), RetAddrFI,
DAG.getConstant(4, getPointerTy()));
}
/// LowerOperation - Provide custom lowering hooks for some operations.
///
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
@ -4654,6 +4655,8 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
case ISD::READCYCLECOUNTER: return LowerREADCYCLCECOUNTER(Op, DAG);
case ISD::VASTART: return LowerVASTART(Op, DAG);
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
}
}

View File

@ -292,10 +292,6 @@ namespace llvm {
///
virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG);
virtual SDOperand PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI,
@ -406,6 +402,8 @@ namespace llvm {
SDOperand LowerREADCYCLCECOUNTER(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG);
};
}