Use new interfaces to correctly lower varargs and return/frame address intrinsics.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19407 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index f6d4979..4fe5ddf 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -304,14 +304,12 @@
   void visitPHI(PHINode &I) { } // PHI nodes are handled specially.
   void visitCall(CallInst &I);
 
-  // FIXME: These should go through the FunctionLoweringInfo object!!!
   void visitVAStart(CallInst &I);
   void visitVANext(VANextInst &I);
   void visitVAArg(VAArgInst &I);
   void visitVAEnd(CallInst &I);
   void visitVACopy(CallInst &I);
-  void visitReturnAddress(CallInst &I);
-  void visitFrameAddress(CallInst &I);
+  void visitFrameReturnAddress(CallInst &I, bool isFrameAddress);
 
   void visitMemSet(CallInst &I);
   void visitMemCpy(CallInst &I);
@@ -576,10 +574,8 @@
     case Intrinsic::vastart:  visitVAStart(I); return;
     case Intrinsic::vaend:    visitVAEnd(I); return;
     case Intrinsic::vacopy:   visitVACopy(I); return;
-    case Intrinsic::returnaddress:
-      visitReturnAddress(I); return;
-    case Intrinsic::frameaddress:
-      visitFrameAddress(I); return;
+    case Intrinsic::returnaddress: visitFrameReturnAddress(I, false); return;
+    case Intrinsic::frameaddress:  visitFrameReturnAddress(I, true); return;
     default:
       // FIXME: IMPLEMENT THESE.
       // readport, writeport, readio, writeio
@@ -651,46 +647,86 @@
   DAG.setRoot(Result.second);
 }
 
-void SelectionDAGLowering::visitVAStart(CallInst &I) {
+std::pair<SDOperand, SDOperand>
+TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
   // We have no sane default behavior, just emit a useful error message and bail
   // out.
-  std::cerr << "Variable arguments support not implemented for this target!\n";
+  std::cerr << "Variable arguments handling not implemented on this target!\n";
   abort();
 }
 
+SDOperand TargetLowering::LowerVAEnd(SDOperand Chain, SDOperand L,
+                                     SelectionDAG &DAG) {
+  // Default to a noop.
+  return Chain;
+}
+
+std::pair<SDOperand,SDOperand>
+TargetLowering::LowerVACopy(SDOperand Chain, SDOperand L, SelectionDAG &DAG) {
+  // Default to returning the input list.
+  return std::make_pair(L, Chain);
+}
+
+std::pair<SDOperand,SDOperand>
+TargetLowering::LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
+                               const Type *ArgTy, SelectionDAG &DAG) {
+  // We have no sane default behavior, just emit a useful error message and bail
+  // out.
+  std::cerr << "Variable arguments handling not implemented on this target!\n";
+  abort();
+}
+
+
+void SelectionDAGLowering::visitVAStart(CallInst &I) {
+  std::pair<SDOperand,SDOperand> Result = TLI.LowerVAStart(DAG.getRoot(), DAG);
+  setValue(&I, Result.first);
+  DAG.setRoot(Result.second);
+}
+
+void SelectionDAGLowering::visitVAArg(VAArgInst &I) {
+  std::pair<SDOperand,SDOperand> Result =
+    TLI.LowerVAArgNext(false, DAG.getRoot(), getValue(I.getOperand(0)), 
+                       I.getType(), DAG);
+  setValue(&I, Result.first);
+  DAG.setRoot(Result.second);
+}
+
 void SelectionDAGLowering::visitVANext(VANextInst &I) {
-  // We have no sane default behavior, just emit a useful error message and bail
-  // out.
-  std::cerr << "Variable arguments support not implemented for this target!\n";
-  abort();
-}
-void SelectionDAGLowering::visitVAArg(VAArgInst &I) {
-  // We have no sane default behavior, just emit a useful error message and bail
-  // out.
-  std::cerr << "Variable arguments support not implemented for this target!\n";
-  abort();
+  std::pair<SDOperand,SDOperand> Result =
+    TLI.LowerVAArgNext(true, DAG.getRoot(), getValue(I.getOperand(0)), 
+                       I.getArgType(), DAG);
+  setValue(&I, Result.first);
+  DAG.setRoot(Result.second);
 }
 
 void SelectionDAGLowering::visitVAEnd(CallInst &I) {
-  // By default, this is a noop.  On almost all targets, this is fine.
+  DAG.setRoot(TLI.LowerVAEnd(DAG.getRoot(), getValue(I.getOperand(1)), DAG));
 }
 
 void SelectionDAGLowering::visitVACopy(CallInst &I) {
-  // By default, vacopy just does a simple pointer copy.
-  setValue(&I, getValue(I.getOperand(1)));
+  std::pair<SDOperand,SDOperand> Result =
+    TLI.LowerVACopy(DAG.getRoot(), getValue(I.getOperand(1)), DAG);
+  setValue(&I, Result.first);
+  DAG.setRoot(Result.second);
 }
 
-void SelectionDAGLowering::visitReturnAddress(CallInst &I) {
-  // It is always conservatively correct for llvm.returnaddress to return 0.
-  setValue(&I, getIntPtrConstant(0));
+
+// It is always conservatively correct for llvm.returnaddress and
+// llvm.frameaddress to return 0.
+std::pair<SDOperand, SDOperand>
+TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain,
+                                        unsigned Depth, SelectionDAG &DAG) {
+  return std::make_pair(DAG.getConstant(0, getPointerTy()), Chain);
 }
 
-void SelectionDAGLowering::visitFrameAddress(CallInst &I) {
-  // It is always conservatively correct for llvm.frameaddress to return 0.
-  setValue(&I, getIntPtrConstant(0));
+void SelectionDAGLowering::visitFrameReturnAddress(CallInst &I, bool isFrame) {
+  unsigned Depth = (unsigned)cast<ConstantUInt>(I.getOperand(1))->getValue();
+  std::pair<SDOperand,SDOperand> Result =
+    TLI.LowerFrameReturnAddress(isFrame, DAG.getRoot(), Depth, DAG);
+  setValue(&I, Result.first);
+  DAG.setRoot(Result.second);
 }
 
-
 void SelectionDAGLowering::visitMemSet(CallInst &I) {
   MVT::ValueType IntPtr = TLI.getPointerTy();
   const Type *IntPtrTy = TLI.getTargetData().getIntPtrType();