[cfe-commits] r70677 - in /cfe/trunk: lib/CodeGen/CGStmt.cpp test/CodeGen/asm.c

Chris Lattner sabre at nondot.org
Sun May 3 01:21:22 PDT 2009


Author: lattner
Date: Sun May  3 03:21:20 2009
New Revision: 70677

URL: http://llvm.org/viewvc/llvm-project?rev=70677&view=rev
Log:
add support for tying asm operands where the  result is smaller than
the input.  This is part of PR3373.


Modified:
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/test/CodeGen/asm.c

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=70677&r1=70676&r2=70677&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sun May  3 03:21:20 2009
@@ -805,9 +805,8 @@
   
   std::vector<LValue> ResultRegDests;
   std::vector<QualType> ResultRegQualTys;
-  
-  std::vector<const llvm::Type *> ResultTypes;
-  
+  std::vector<const llvm::Type *> ResultRegTypes;
+  std::vector<const llvm::Type *> ResultTruncRegTypes;
   std::vector<const llvm::Type*> ArgTypes;
   std::vector<llvm::Value*> Args;
 
@@ -832,11 +831,38 @@
     if (!Constraints.empty())
       Constraints += ',';
 
+    // If this is a register output, then make the inline asm return it
+    // by-value.  If this is a memory result, return the value by-reference.
     if (!Info.allowsMemory() && !hasAggregateLLVMType(OutExpr->getType())) {
+      Constraints += "=" + OutputConstraint;
       ResultRegQualTys.push_back(OutExpr->getType());
       ResultRegDests.push_back(Dest);
-      ResultTypes.push_back(ConvertTypeForMem(OutExpr->getType()));
-      Constraints += "=" + OutputConstraint;
+      ResultRegTypes.push_back(ConvertTypeForMem(OutExpr->getType()));
+      ResultTruncRegTypes.push_back(ResultRegTypes.back());
+      
+      // If this output is tied to an input, and if the input is larger, then
+      // we need to set the actual result type of the inline asm node to be the
+      // same as the input type.
+      if (Info.hasMatchingInput()) {
+        unsigned InputNo = ~0;
+        for (unsigned i = 0, e = S.getNumInputs(); i != e; ++i)
+          if (InputConstraintInfos[i].hasTiedOperand() &&
+              InputConstraintInfos[i].getTiedOperand() == i) {
+            InputNo = i;
+            break;
+          }
+        assert(InputNo != ~0U && "Didn't find matching input!");
+        
+        QualType InputTy = S.getInputExpr(InputNo)->getType();
+        QualType OutputTy = OutExpr->getType();
+        
+        uint64_t InputSize = getContext().getTypeSize(InputTy);
+        if (getContext().getTypeSize(OutputTy) < InputSize) {
+          // Form the asm to return the value as a larger integer type.
+          ResultRegTypes.back() = llvm::IntegerType::get((unsigned)InputSize);
+        }
+      }
+      
     } else {
       ArgTypes.push_back(Dest.getAddress()->getType());
       Args.push_back(Dest.getAddress());
@@ -935,12 +961,12 @@
   }
 
   const llvm::Type *ResultType;
-  if (ResultTypes.empty())
+  if (ResultRegTypes.empty())
     ResultType = llvm::Type::VoidTy;
-  else if (ResultTypes.size() == 1)
-    ResultType = ResultTypes[0];
+  else if (ResultRegTypes.size() == 1)
+    ResultType = ResultRegTypes[0];
   else
-    ResultType = llvm::StructType::get(ResultTypes);
+    ResultType = llvm::StructType::get(ResultRegTypes);
   
   const llvm::FunctionType *FTy = 
     llvm::FunctionType::get(ResultType, ArgTypes, false);
@@ -951,14 +977,37 @@
   llvm::CallInst *Result = Builder.CreateCall(IA, Args.begin(), Args.end());
   Result->addAttribute(~0, llvm::Attribute::NoUnwind);
   
-  if (ResultTypes.size() == 1) {
-    EmitStoreThroughLValue(RValue::get(Result), ResultRegDests[0],
-                           ResultRegQualTys[0]);
+  
+  // Extract all of the register value results from the asm.
+  std::vector<llvm::Value*> RegResults;
+  if (ResultRegTypes.size() == 1) {
+    RegResults.push_back(Result);
   } else {
-    for (unsigned i = 0, e = ResultTypes.size(); i != e; ++i) {
+    for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
       llvm::Value *Tmp = Builder.CreateExtractValue(Result, i, "asmresult");
-      EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i],
-                             ResultRegQualTys[i]);
+      RegResults.push_back(Tmp);
     }
   }
+  
+  for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {
+    llvm::Value *Tmp = RegResults[i];
+    
+    // If the result type of the LLVM IR asm doesn't match the result type of
+    // the expression, do the conversion.
+    if (ResultRegTypes[i] != ResultTruncRegTypes[i]) {
+      const llvm::Type *TruncTy = ResultTruncRegTypes[i];
+      // Truncate the integer result to the right size, note that
+      // ResultTruncRegTypes can be a pointer.
+      uint64_t ResSize = CGM.getTargetData().getTypeSizeInBits(TruncTy);
+      Tmp = Builder.CreateTrunc(Tmp, llvm::IntegerType::get((unsigned)ResSize));
+      
+      if (Tmp->getType() != TruncTy) {
+        assert(isa<llvm::PointerType>(TruncTy));
+        Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
+      }
+    }
+    
+    EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i],
+                           ResultRegQualTys[i]);
+  }
 }

Modified: cfe/trunk/test/CodeGen/asm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/asm.c?rev=70677&r1=70676&r2=70677&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/asm.c (original)
+++ cfe/trunk/test/CodeGen/asm.c Sun May  3 03:21:20 2009
@@ -60,7 +60,14 @@
   return output;
 }
 
-
+// PR3373
+unsigned char t12(unsigned input) {
+  unsigned char output;
+  __asm__("xyz"
+          : "=a" (output)
+          : "0" (input));
+  return output;
+}
 
 
 struct S {





More information about the cfe-commits mailing list