]> granicus.if.org Git - clang/commitdiff
Don't use indirect memory destinations for inline asm. Fixes 6841383.
authorAnders Carlsson <andersca@mac.com>
Fri, 1 May 2009 00:16:04 +0000 (00:16 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 1 May 2009 00:16:04 +0000 (00:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70523 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGStmt.cpp
test/CodeGen/asm-2.c [new file with mode: 0644]

index 0837dd04898827424f8ef050986f83ef237ca870..63664e1a3a7f9111ce2405810b77e1dd01d48001 100644 (file)
@@ -781,8 +781,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
   
   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 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
     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 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
       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]);
+    }
+  }
 }
diff --git a/test/CodeGen/asm-2.c b/test/CodeGen/asm-2.c
new file mode 100644 (file)
index 0000000..a58a781
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: clang-cc -emit-llvm %s -o %t -arch=i386 -O2 &&
+// RUN: not grep "load" %t
+
+// <rdar://problem/6841383>
+int cpuid(unsigned data) {
+  int a, b;
+  
+  asm("xyz" :"=a"(a), "=d"(b) : "a"(data));
+  return a + b;
+}
\ No newline at end of file