Finish off bug 680, allowing targets to custom lower frame and return
authorNate Begeman <natebegeman@mac.com>
Mon, 29 Jan 2007 22:58:52 +0000 (22:58 +0000)
committerNate Begeman <natebegeman@mac.com>
Mon, 29 Jan 2007 22:58:52 +0000 (22:58 +0000)
address nodes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33636 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/llvm/CodeGen/SelectionDAGNodes.h
include/llvm/Target/TargetLowering.h
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/Alpha/AlphaISelLowering.cpp
lib/Target/IA64/IA64ISelLowering.cpp
lib/Target/IA64/IA64ISelLowering.h
lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/Sparc/SparcISelDAGToDAG.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h

index 11c6ad6c538fea3684477b299663a4e0aff7b6fd..b928387b78dcefa9899d58324a1e8d172db7f219 100644 (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.
index 49d6624f8ecec111c883422e5d781c19c3fb6e70..35fa59e379874841c35995c9cdb26e1438f27fd9 100644 (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.
index 6eb43e1d8e4e9607e95b8b3604d3e04e791f2232..c3289fc1e70b750a5f0369e932ee3617806cc4ec 100644 (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));
index 97fb8c5a049cc9e07397010c9fa45747960a368b..8bed6f7a26fa3130190ad998cc92accac4bb11c8 100644 (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: {
index df7440f792f037fdb4182fa9f22b20dad3d4cdef..3b452979aa534e47356c7b31f31613d9bbcb6d68 100644 (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,
index e2268d212b6f4a8b0fc4a88d38a8017dfe575210..55b22aae39766ab3ba9a8394866ec3fce9c34db4 100644 (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();
 }
 
 //===----------------------------------------------------------------------===//
index f0e5be6a0c99a3b98ce7fad2adc6facf54432dd5..7df996dd0fa1529c9e5477e432e1c8a14b4f09f0 100644 (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();
index 2d14a2bc5ffe483cb0007f2839b3dc31060a1cec..1c7c51db0d1ab023ea9868224ef08e2e8a315bd4 100644 (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();
 }
index 9918c4bfe38d87886ab160c7e569c58f7bfdbe3d..6bc55348ce93ce36c797de6297077a04d70b7b62 100644 (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);
   };
index 041ff36af3809ec58ea179497d85d69646e381f0..88815a7c5adff9bdb3963eb7bcd53cdbe62613a4 100644 (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();
 }
index f361b4670a54f55502f5d25010b551a787ca3ccf..647007e86bfdb47c982dd09cb046e185d8d80400 100644 (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 *
index 69ca2c190f84a50c6561a71ef156ede450adc053..71cac03150a0b9018ecd1cc79222abbe1b9acc69 100644 (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);
   }
 }
 
index a9df1f8a66f8e5dfd3f5c293b2b8d7f53e68494a..4157697b141a538327f69045dd5b83b9c8fe44bd 100644 (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);
   };
 }