[llvm-commits] [llvm] r51420 - in /llvm/trunk: lib/Target/CBackend/CBackend.cpp test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll

Chris Lattner sabre at nondot.org
Wed May 21 23:19:38 PDT 2008


Author: lattner
Date: Thu May 22 01:19:37 2008
New Revision: 51420

URL: http://llvm.org/viewvc/llvm-project?rev=51420&view=rev
Log:
Add support for multiple-return values in inline asm.  This should
get inline asm working as well as it did previously with the CBE
with the new MRV support for inline asm.

Added:
    llvm/trunk/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll
Modified:
    llvm/trunk/lib/Target/CBackend/CBackend.cpp

Modified: llvm/trunk/lib/Target/CBackend/CBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CBackend/CBackend.cpp?rev=51420&r1=51419&r2=51420&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CBackend/CBackend.cpp (original)
+++ llvm/trunk/lib/Target/CBackend/CBackend.cpp Thu May 22 01:19:37 2008
@@ -2598,11 +2598,8 @@
 }
 
 void CWriter::visitCallInst(CallInst &I) {
-  //check if we have inline asm
-  if (isInlineAsm(I)) {
-    visitInlineAsm(I);
-    return;
-  }
+  if (isa<InlineAsm>(I.getOperand(0)))
+    return visitInlineAsm(I);
 
   bool WroteCallee = false;
 
@@ -2920,53 +2917,64 @@
   InlineAsm* as = cast<InlineAsm>(CI.getOperand(0));
   std::vector<InlineAsm::ConstraintInfo> Constraints = as->ParseConstraints();
   std::vector<std::pair<std::string, Value*> > Input;
-  std::vector<std::pair<std::string, Value*> > Output;
+  std::vector<std::pair<std::string, std::pair<Value*, int> > > Output;
   std::string Clobber;
-  int count = CI.getType() == Type::VoidTy ? 1 : 0;
+  unsigned ValueCount = 0;
+  
+  std::vector<std::pair<Value*, int> > ResultVals;
+  if (CI.getType() == Type::VoidTy)
+    ;
+  else if (const StructType *ST = dyn_cast<StructType>(CI.getType())) {
+    for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
+      ResultVals.push_back(std::make_pair(&CI, (int)i));
+  } else {
+    ResultVals.push_back(std::make_pair(&CI, -1));
+  }
+  
   for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
          E = Constraints.end(); I != E; ++I) {
     assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
-    std::string c = 
-      InterpretASMConstraint(*I);
-    switch(I->Type) {
-    default:
-      assert(0 && "Unknown asm constraint");
-      break;
+    std::string C = InterpretASMConstraint(*I);
+    if (C.empty()) continue;
+    
+    switch (I->Type) {
+    default: assert(0 && "Unknown asm constraint");
     case InlineAsm::isInput: {
-      if (c.size()) {
-        Input.push_back(std::make_pair(c, count ? CI.getOperand(count) : &CI));
-        ++count; //consume arg
-      }
+      assert(ValueCount >= ResultVals.size() && "Input can't refer to result");
+      Value *V = CI.getOperand(ValueCount-ResultVals.size());
+      Input.push_back(std::make_pair(C, V));
       break;
     }
     case InlineAsm::isOutput: {
-      if (c.size()) {
-        Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+c),
-                                        count ? CI.getOperand(count) : &CI));
-        ++count; //consume arg
-      }
-      break;
-    }
-    case InlineAsm::isClobber: {
-      if (c.size()) 
-        Clobber += ",\"" + c + "\"";
+      std::pair<Value*, int> V;
+      if (ValueCount < ResultVals.size())
+        V = ResultVals[ValueCount];
+      else
+        V = std::make_pair(CI.getOperand(ValueCount-ResultVals.size()), -1);
+      Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+C),
+                                      V));
       break;
     }
+    case InlineAsm::isClobber:
+      Clobber += ",\"" + C + "\"";
+      continue;  // Not an actual argument.
     }
+    ++ValueCount; // Consumes an argument.
   }
   
-  //fix up the asm string for gcc
+  // Fix up the asm string for gcc.
   std::string asmstr = gccifyAsm(as->getAsmString());
   
   Out << "__asm__ volatile (\"" << asmstr << "\"\n";
   Out << "        :";
-  for (std::vector<std::pair<std::string, Value*> >::iterator I =Output.begin(),
-         E = Output.end(); I != E; ++I) {
-    Out << "\"" << I->first << "\"(";
-    writeOperandRaw(I->second);
+  for (unsigned i = 0, e = Output.size(); i != e; ++i) {
+    if (i)
+      Out << ", ";
+    Out << "\"" << Output[i].first << "\"(";
+    writeOperandRaw(Output[i].second.first);
+    if (Output[i].second.second != -1)
+      Out << ".field" << Output[i].second.second; // Multiple retvals.
     Out << ")";
-    if (I + 1 != E)
-      Out << ",";
   }
   Out << "\n        :";
   for (std::vector<std::pair<std::string, Value*> >::iterator I = Input.begin(),

Added: llvm/trunk/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll?rev=51420&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll (added)
+++ llvm/trunk/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll Thu May 22 01:19:37 2008
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | llc -march=c
+
+declare {i32, i32} @foo()
+
+define i32 @test() {
+  %A = call {i32, i32} @foo()
+  %B = getresult {i32, i32} %A, 0
+  %C = getresult {i32, i32} %A, 1
+  %D = add i32 %B, %C
+  ret i32 %D
+}
+
+define i32 @test2() {
+  %A = call {i32, i32} asm sideeffect "...", "={cx},={di},~{dirflag},~{fpsr},~{flags},~{memory}"()
+  %B = getresult {i32, i32} %A, 0
+  %C = getresult {i32, i32} %A, 1
+  %D = add i32 %B, %C
+  ret i32 %D
+}





More information about the llvm-commits mailing list