Don't use indirect memory destinations for inline asm. Fixes 6841383.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70523 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 0837dd0..63664e1 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -781,8 +781,8 @@
   
   std::string Constraints;
   
-  llvm::Value *ResultAddr = 0;
-  const llvm::Type *ResultType = llvm::Type::VoidTy;
+  std::vector<llvm::Value *> ResultAddrs;
+  std::vector<const llvm::Type *> ResultTypes;
   
   std::vector<const llvm::Type*> ArgTypes;
   std::vector<llvm::Value*> Args;
@@ -812,18 +812,17 @@
     LValue Dest = EmitLValue(OutExpr);
     const llvm::Type *DestValueType = 
       cast<llvm::PointerType>(Dest.getAddress()->getType())->getElementType();
-    
-    // If the first output operand is not a memory dest, we'll
-    // make it the return value.
-    if (i == 0 && !Info.allowsMemory() && DestValueType->isSingleValueType()) {
-      ResultAddr = Dest.getAddress();
-      ResultType = DestValueType;
+
+    if (i != 0)
+      Constraints += ',';
+
+    if (!Info.allowsMemory() && DestValueType->isSingleValueType()) {
+      ResultAddrs.push_back(Dest.getAddress());
+      ResultTypes.push_back(DestValueType);
       Constraints += "=" + OutputConstraint;
     } else {
       ArgTypes.push_back(Dest.getAddress()->getType());
       Args.push_back(Dest.getAddress());
-      if (i != 0)
-        Constraints += ',';
       Constraints += "=*";
       Constraints += OutputConstraint;
     }
@@ -900,17 +899,30 @@
       Constraints += ',';
     Constraints += MachineClobbers;
   }
-    
+
+  const llvm::Type *ResultType;
+  if (ResultTypes.empty())
+    ResultType = llvm::Type::VoidTy;
+  else if (ResultTypes.size() == 1)
+    ResultType = ResultTypes[0];
+  else
+    ResultType = llvm::StructType::get(ResultTypes);
+  
   const llvm::FunctionType *FTy = 
     llvm::FunctionType::get(ResultType, ArgTypes, false);
   
   llvm::InlineAsm *IA = 
     llvm::InlineAsm::get(FTy, AsmString, Constraints, 
                          S.isVolatile() || S.getNumOutputs() == 0);
-  llvm::CallInst *Result
-    = Builder.CreateCall(IA, Args.begin(), Args.end(), "");
+  llvm::CallInst *Result = Builder.CreateCall(IA, Args.begin(), Args.end());
   Result->addAttribute(~0, llvm::Attribute::NoUnwind);
   
-  if (ResultAddr) // FIXME: volatility
-    Builder.CreateStore(Result, ResultAddr);
+  if (ResultTypes.size() == 1) {
+    Builder.CreateStore(Result, ResultAddrs[0]);
+  } else {
+    for (unsigned i = 0, e = ResultTypes.size(); i != e; ++i) {
+      llvm::Value *Tmp = Builder.CreateExtractValue(Result, i, "asmresult");
+      Builder.CreateStore(Tmp, ResultAddrs[i]);
+    }
+  }
 }