From eda5997cc8e2ddaea20bc5cbb211622294320af7 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Mon, 29 Jan 2007 22:58:52 +0000 Subject: [PATCH] Finish off bug 680, allowing targets to custom lower frame and return address nodes. llvm-svn: 33636 --- llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 7 ++++ llvm/include/llvm/Target/TargetLowering.h | 8 ---- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 10 +++++ .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 + .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 32 ++++----------- llvm/lib/Target/ARM/ARMISelLowering.cpp | 3 ++ llvm/lib/Target/Alpha/AlphaISelLowering.cpp | 3 ++ llvm/lib/Target/IA64/IA64ISelLowering.cpp | 11 ++--- llvm/lib/Target/IA64/IA64ISelLowering.h | 4 -- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 4 ++ llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp | 4 ++ llvm/lib/Target/X86/X86ISelLowering.cpp | 41 ++++++++++--------- llvm/lib/Target/X86/X86ISelLowering.h | 6 +-- 13 files changed, 69 insertions(+), 66 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 11c6ad6c538f..b928387b78dc 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -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. diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h index 49d6624f8ece..35fa59e37987 100644 --- a/llvm/include/llvm/Target/TargetLowering.h +++ b/llvm/include/llvm/Target/TargetLowering.h @@ -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 - 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. diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 6eb43e1d8e4e..c3289fc1e70b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -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)); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 97fb8c5a049c..8bed6f7a26fa 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -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: { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index df7440f792f0..3b452979aa53 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -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 -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(I.getOperand(1))->getZExtValue(); - std::pair 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, diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index e2268d212b6f..55b22aae3976 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -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(); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Alpha/AlphaISelLowering.cpp b/llvm/lib/Target/Alpha/AlphaISelLowering.cpp index f0e5be6a0c99..7df996dd0fa1 100644 --- a/llvm/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/llvm/lib/Target/Alpha/AlphaISelLowering.cpp @@ -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(); diff --git a/llvm/lib/Target/IA64/IA64ISelLowering.cpp b/llvm/lib/Target/IA64/IA64ISelLowering.cpp index 2d14a2bc5ffe..1c7c51db0d1a 100644 --- a/llvm/lib/Target/IA64/IA64ISelLowering.cpp +++ b/llvm/lib/Target/IA64/IA64ISelLowering.cpp @@ -532,13 +532,6 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, return std::make_pair(RetVal, Chain); } -std::pair 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(); } diff --git a/llvm/lib/Target/IA64/IA64ISelLowering.h b/llvm/lib/Target/IA64/IA64ISelLowering.h index 9918c4bfe38d..6bc55348ce93 100644 --- a/llvm/lib/Target/IA64/IA64ISelLowering.h +++ b/llvm/lib/Target/IA64/IA64ISelLowering.h @@ -66,10 +66,6 @@ namespace llvm { /// (currently, only "ret void") virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); - virtual std::pair - LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, - SelectionDAG &DAG); - // XXX virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI, // XXX MachineBasicBlock *MBB); }; diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 041ff36af380..88815a7c5adf 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -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(); } diff --git a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp index f361b4670a54..647007e86bfd 100644 --- a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -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 * diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 69ca2c190f84..71cac03150a0 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -1940,25 +1940,6 @@ SDOperand X86TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) { -std::pair 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(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(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); } } diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index a9df1f8a66f8..4157697b141a 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -292,10 +292,6 @@ namespace llvm { /// virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); - virtual std::pair - 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); }; }