XCore target: Add target specific EmitVAArg

This is so aggregates can be passed as var args too.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188664 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index bab77e6..4b1c565 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -5370,13 +5370,53 @@
 // Xcore ABI Implementation
 //===----------------------------------------------------------------------===//
 namespace {
+class XCoreABIInfo : public DefaultABIInfo {
+public:
+  XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+  virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+                                 CodeGenFunction &CGF) const;
+};
+
 class XcoreTargetCodeGenInfo : public TargetCodeGenInfo {
 public:
   XcoreTargetCodeGenInfo(CodeGenTypes &CGT)
-    :TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
+    :TargetCodeGenInfo(new XCoreABIInfo(CGT)) {}
 };
 } // end anonymous namespace
 
+llvm::Value *XCoreABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+                                     CodeGenFunction &CGF) const {
+  ABIArgInfo AI = classifyArgumentType(Ty);
+  CGBuilderTy &Builder = CGF.Builder;
+  llvm::Type *ArgTy = CGT.ConvertType(Ty);
+  if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
+    AI.setCoerceToType(ArgTy);
+
+  // handle the VAList
+  llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr,
+                                                       CGF.Int8PtrPtrTy);
+  llvm::Value *AP = Builder.CreateLoad(VAListAddrAsBPP);
+  llvm::Value *APN = Builder.CreateConstGEP1_32(AP, 4);
+  Builder.CreateStore(APN, VAListAddrAsBPP);
+
+  // handle the argument
+  llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
+  switch (AI.getKind()) {
+  default:
+  case ABIArgInfo::Expand:
+    llvm_unreachable("Unsupported ABI kind for va_arg");
+  case ABIArgInfo::Ignore:
+    return llvm::UndefValue::get(ArgPtrTy);
+  case ABIArgInfo::Extend:
+  case ABIArgInfo::Direct:
+    return Builder.CreatePointerCast(AP, ArgPtrTy);
+  case ABIArgInfo::Indirect:
+    llvm::Value *ArgAddr;
+    ArgAddr = Builder.CreateBitCast(AP, llvm::PointerType::getUnqual(ArgPtrTy));
+    ArgAddr = Builder.CreateLoad(ArgAddr);
+    return Builder.CreatePointerCast(ArgAddr, ArgPtrTy);
+  }
+}
 
 //===----------------------------------------------------------------------===//
 // Driver code