]> granicus.if.org Git - clang/commitdiff
implement support for asm outputs targetting non-simple lvalue destinations
authorChris Lattner <sabre@nondot.org>
Sun, 3 May 2009 07:53:25 +0000 (07:53 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 3 May 2009 07:53:25 +0000 (07:53 +0000)
like bitfields.  incidentally llvm-gcc crashes on this sort of thing also. :)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70675 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGStmt.cpp
test/CodeGen/asm.c

index f435f9cfb402fabeb2c8f2e734ad34feda68bb60..aefb3e5f958215cc34548edd8f41bc24966524d7 100644 (file)
@@ -803,7 +803,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
   
   std::string Constraints;
   
-  std::vector<llvm::Value *> ResultAddrs;
+  std::vector<LValue> ResultRegDests;
+  std::vector<QualType> ResultRegQualTys;
+  
   std::vector<const llvm::Type *> ResultTypes;
   
   std::vector<const llvm::Type*> ArgTypes;
@@ -827,15 +829,13 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
     OutExpr = OutExpr->IgnoreParenNoopCasts(getContext());
     
     LValue Dest = EmitLValue(OutExpr);
-    const llvm::Type *DestValueType = 
-      cast<llvm::PointerType>(Dest.getAddress()->getType())->getElementType();
-
-    if (i != 0)
+    if (!Constraints.empty())
       Constraints += ',';
 
-    if (!Info.allowsMemory() && DestValueType->isSingleValueType()) {
-      ResultAddrs.push_back(Dest.getAddress());
-      ResultTypes.push_back(DestValueType);
+    if (!Info.allowsMemory() && !hasAggregateLLVMType(OutExpr->getType())) {
+      ResultRegQualTys.push_back(OutExpr->getType());
+      ResultRegDests.push_back(Dest);
+      ResultTypes.push_back(ConvertTypeForMem(OutExpr->getType()));
       Constraints += "=" + OutputConstraint;
     } else {
       ArgTypes.push_back(Dest.getAddress()->getType());
@@ -867,7 +867,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
 
     TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
 
-    if (i != 0 || S.getNumOutputs() > 0)
+    if (!Constraints.empty())
       Constraints += ',';
     
     // Simplify the input constraint.
@@ -952,11 +952,13 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
   Result->addAttribute(~0, llvm::Attribute::NoUnwind);
   
   if (ResultTypes.size() == 1) {
-    Builder.CreateStore(Result, ResultAddrs[0]);
+    EmitStoreThroughLValue(RValue::get(Result), ResultRegDests[0],
+                           ResultRegQualTys[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]);
+      EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i],
+                             ResultRegQualTys[i]);
     }
   }
 }
index 757a2740a7d082eebb3148f4f68dbd493094551e..0e9c7b243fcbd8bf45fb33eb1adfafbfb18aa165 100644 (file)
@@ -59,3 +59,14 @@ unsigned t11(signed char input) {
           : "0" (input));
   return output;
 }
+
+
+
+
+struct S {
+  int a : 4;
+};
+
+void test13(struct S *P) {
+  __asm__("abc %0" : "=r"(P->a) );
+}