If we support structs as va_list, we must pass pointers to them to va_copy
See last commit for LangRef, this implements it on all targets.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22273 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index b71f618..178c533 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -749,14 +749,12 @@
   }
 
   if (ObsoleteVarArgs && NewVarArgs)
-  {
-    std::cerr << "This file is corrupt in that it uses both new and old style varargs\n";
-    abort();
-  }
+    ThrowException("This file is corrupt in that it uses both new and old style varargs");
 
   if(ObsoleteVarArgs) {
     if(Function* F = Result->getNamedFunction("llvm.va_start")) {
-      assert(F->arg_size() == 0 && "Obsolete va_start takes 0 argument!");
+      if (F->arg_size() != 0)
+        ThrowException("Obsolete va_start takes 0 argument!");
       
       //foo = va_start()
       // ->
@@ -782,7 +780,9 @@
     }
     
     if(Function* F = Result->getNamedFunction("llvm.va_end")) {
-      assert(F->arg_size() == 1 && "Obsolete va_end takes 1 argument!");
+      if(F->arg_size() != 1)
+        ThrowException("Obsolete va_end takes 1 argument!");
+
       //vaend foo
       // ->
       //bar = alloca 1 of typeof(foo)
@@ -804,24 +804,29 @@
     }
 
     if(Function* F = Result->getNamedFunction("llvm.va_copy")) {
-      assert(F->arg_size() == 1 && "Obsolete va_copy takes 1 argument!");
+      if(F->arg_size() != 1)
+        ThrowException("Obsolete va_copy takes 1 argument!");
       //foo = vacopy(bar)
       // ->
       //a = alloca 1 of typeof(foo)
-      //vacopy(a, bar)
+      //b = alloca 1 of typeof(foo)
+      //store bar -> b
+      //vacopy(a, b)
       //foo = load a
       
       const Type* RetTy = Type::getPrimitiveType(Type::VoidTyID);
       const Type* ArgTy = F->getFunctionType()->getReturnType();
       const Type* ArgTyPtr = PointerType::get(ArgTy);
       Function* NF = Result->getOrInsertFunction("llvm.va_copy", 
-                                                 RetTy, ArgTyPtr, ArgTy, 0);
+                                                 RetTy, ArgTyPtr, ArgTyPtr, 0);
 
       while (!F->use_empty()) {
         CallInst* CI = cast<CallInst>(F->use_back());
         AllocaInst* a = new AllocaInst(ArgTy, 0, "vacopy.fix.1", CI);
-        new CallInst(NF, a, CI->getOperand(1), "", CI);
-        Value* foo = new LoadInst(a, "vacopy.fix.2", CI);
+        AllocaInst* b = new AllocaInst(ArgTy, 0, "vacopy.fix.2", CI);
+        new StoreInst(CI->getOperand(1), b, CI);
+        new CallInst(NF, a, b, "", CI);
+        Value* foo = new LoadInst(a, "vacopy.fix.3", CI);
         CI->replaceAllUsesWith(foo);
         CI->getParent()->getInstList().erase(CI);
       }
diff --git a/lib/Bytecode/Reader/ReaderWrappers.cpp b/lib/Bytecode/Reader/ReaderWrappers.cpp
index c000c9a..a198447 100644
--- a/lib/Bytecode/Reader/ReaderWrappers.cpp
+++ b/lib/Bytecode/Reader/ReaderWrappers.cpp
@@ -221,20 +221,24 @@
     //foo = vacopy(bar)
     // ->
     //a = alloca 1 of typeof(foo)
-    //vacopy(a, bar)
+    //b = alloca 1 of typeof(foo)
+    //store bar -> b
+    //vacopy(a, b)
     //foo = load a
     
     const Type* RetTy = Type::getPrimitiveType(Type::VoidTyID);
     const Type* ArgTy = F->getFunctionType()->getReturnType();
     const Type* ArgTyPtr = PointerType::get(ArgTy);
     Function* NF = M->getOrInsertFunction("llvm.va_copy", 
-                                          RetTy, ArgTyPtr, ArgTy, 0);
+                                          RetTy, ArgTyPtr, ArgTyPtr, 0);
     
     for(Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E;)
       if (CallInst* CI = dyn_cast<CallInst>(*I++)) {
         AllocaInst* a = new AllocaInst(ArgTy, 0, "vacopy.fix.1", CI);
-        new CallInst(NF, a, CI->getOperand(1), "", CI);
-        Value* foo = new LoadInst(a, "vacopy.fix.2", CI);
+        AllocaInst* b = new AllocaInst(ArgTy, 0, "vacopy.fix.2", CI);
+        new StoreInst(CI->getOperand(1), b, CI);
+        new CallInst(NF, a, b, "", CI);
+        Value* foo = new LoadInst(a, "vacopy.fix.3", CI);
         CI->replaceAllUsesWith(foo);
         CI->getParent()->getInstList().erase(CI);
       }
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 0c94ea7..fa6d6d4 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -855,10 +855,11 @@
 std::pair<SDOperand,SDOperand>
 TargetLowering::LowerVACopy(SDOperand Chain, SDOperand Src, SDOperand Dest, 
                             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();
+  //Default to returning the input list
+  SDOperand Val = DAG.getLoad(getPointerTy(), Chain, Src, DAG.getSrcValue(NULL));
+  SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
+                                 Val, Dest, DAG.getSrcValue(NULL));
+  return std::make_pair(Result, Result);
 }
 
 std::pair<SDOperand,SDOperand>
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 6597993..c30b306 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -1495,7 +1495,7 @@
         Out << "0; ";
         Out << "va_copy(*(va_list*)";
         writeOperand(I.getOperand(1));
-        Out << ", *(va_list*)&";
+        Out << ", *(va_list*)";
         writeOperand(I.getOperand(2));
         Out << ')';
         return;
diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp
index 6597993..c30b306 100644
--- a/lib/Target/CBackend/Writer.cpp
+++ b/lib/Target/CBackend/Writer.cpp
@@ -1495,7 +1495,7 @@
         Out << "0; ";
         Out << "va_copy(*(va_list*)";
         writeOperand(I.getOperand(1));
-        Out << ", *(va_list*)&";
+        Out << ", *(va_list*)";
         writeOperand(I.getOperand(2));
         Out << ')';
         return;
diff --git a/lib/Target/IA64/IA64ISelPattern.cpp b/lib/Target/IA64/IA64ISelPattern.cpp
index 0830468..804ad99 100644
--- a/lib/Target/IA64/IA64ISelPattern.cpp
+++ b/lib/Target/IA64/IA64ISelPattern.cpp
@@ -120,10 +120,6 @@
     LowerVAArgNext(SDOperand Chain, SDOperand VAList,
                    const Type *ArgTy, SelectionDAG &DAG);
 
-    virtual std::pair<SDOperand,SDOperand>
-    LowerVACopy(SDOperand Chain, SDOperand Src, SDOperand Dest, 
-                SelectionDAG &DAG);
-
     virtual std::pair<SDOperand, SDOperand>
     LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
                             SelectionDAG &DAG);
@@ -413,15 +409,6 @@
   return std::make_pair(Result, Chain);
 }
 
-std::pair<SDOperand,SDOperand>
-IA64TargetLowering::LowerVACopy(SDOperand Chain, SDOperand Src, 
-                                SDOperand Dest, SelectionDAG &DAG)
-{
-  SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                 Src, Dest, DAG.getSrcValue(NULL));
-  return std::make_pair(Result, Result);
-}
-
 std::pair<SDOperand, SDOperand> IA64TargetLowering::
 LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
                         SelectionDAG &DAG) {
diff --git a/lib/Target/PowerPC/PPC64ISelPattern.cpp b/lib/Target/PowerPC/PPC64ISelPattern.cpp
index 20fd724..6761ab1 100644
--- a/lib/Target/PowerPC/PPC64ISelPattern.cpp
+++ b/lib/Target/PowerPC/PPC64ISelPattern.cpp
@@ -104,10 +104,6 @@
     LowerVAArgNext(SDOperand Chain, SDOperand VAList,
                    const Type *ArgTy, SelectionDAG &DAG);
 
-    virtual std::pair<SDOperand,SDOperand>
-    LowerVACopy(SDOperand Chain, SDOperand Src, SDOperand Dest,
-                SelectionDAG &DAG);
-
     virtual std::pair<SDOperand, SDOperand>
     LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
                             SelectionDAG &DAG);
@@ -390,16 +386,6 @@
   return std::make_pair(Result, Chain);
 }
 
-std::pair<SDOperand,SDOperand>
-PPC64TargetLowering::LowerVACopy(SDOperand Chain, SDOperand Src, 
-                                 SDOperand Dest, SelectionDAG &DAG)
-{
-  SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                 Src, Dest, DAG.getSrcValue(NULL));
-  return std::make_pair(Result, Result);
-}
-
-
 std::pair<SDOperand, SDOperand> PPC64TargetLowering::
 LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
                         SelectionDAG &DAG) {
diff --git a/lib/Target/SparcV9/SparcV9BurgISel.cpp b/lib/Target/SparcV9/SparcV9BurgISel.cpp
index cc2c81f..a6722b1 100644
--- a/lib/Target/SparcV9/SparcV9BurgISel.cpp
+++ b/lib/Target/SparcV9/SparcV9BurgISel.cpp
@@ -2881,11 +2881,18 @@
     return true;                        // no-op on SparcV9
 
   case Intrinsic::vacopy:
-    // Simple store of current va_list (arg2) to new va_list (arg1)
-    mvec.push_back(BuildMI(V9::STXi, 3).
-                   addReg(callInstr.getOperand(2)).
-                   addReg(callInstr.getOperand(1)).addSImm(0));
-    return true;
+    {
+      MachineCodeForInstruction& m1 = MachineCodeForInstruction::get(&callInstr);
+      TmpInstruction* VReg = 
+        new TmpInstruction(m1, callInstr.getOperand(1)->getType());
+      
+      // Simple store of current va_list (arg2) to new va_list (arg1)
+      mvec.push_back(BuildMI(V9::LDXi, 3).
+                     addReg(callInstr.getOperand(2)).addSImm(0).addRegDef(VReg));
+      mvec.push_back(BuildMI(V9::STXi, 3).
+                     addReg(VReg).addReg(callInstr.getOperand(1)).addSImm(0));
+      return true;
+    }
   }
 }
 
diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp
index d28de28..e858c4c 100644
--- a/lib/Target/X86/X86ISelPattern.cpp
+++ b/lib/Target/X86/X86ISelPattern.cpp
@@ -182,10 +182,6 @@
     LowerVAArgNext(SDOperand Chain, SDOperand VAList,
                    const Type *ArgTy, SelectionDAG &DAG);
 
-    virtual std::pair<SDOperand,SDOperand>
-    LowerVACopy(SDOperand Chain, SDOperand Src, SDOperand Dest, 
-                SelectionDAG &DAG);
-
     virtual std::pair<SDOperand, SDOperand>
     LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
                             SelectionDAG &DAG);
@@ -475,15 +471,6 @@
   return std::make_pair(Result, Chain);
 }
 
-std::pair<SDOperand,SDOperand>
-X86TargetLowering::LowerVACopy(SDOperand Chain, SDOperand Src, 
-                               SDOperand Dest, SelectionDAG &DAG)
-{
-  SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                 Src, Dest, DAG.getSrcValue(NULL));
-  return std::make_pair(Result, Result);
-}
-
 //===----------------------------------------------------------------------===//
 //                    Fast Calling Convention implementation
 //===----------------------------------------------------------------------===//