]> granicus.if.org Git - clang/commitdiff
allow references to the larger value in a tied constraint
authorChris Lattner <sabre@nondot.org>
Sun, 3 May 2009 08:32:32 +0000 (08:32 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 3 May 2009 08:32:32 +0000 (08:32 +0000)
from the asm string, but reject references to the smaller one.

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

lib/Sema/SemaStmt.cpp
test/CodeGen/asm.c

index cb237870f84158ba35a3282feb29fbb71f668632..0c181ecf0135d36f46e1e04da5fceaab2595b4e3 100644 (file)
@@ -1052,26 +1052,42 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
       // They are ok if they are the same size.  Tying void* to int is ok if
       // they are the same size, for example.  This also allows tying void* to
       // int*.
-      if (Context.getTypeSize(OutTy) == Context.getTypeSize(InTy))
+      uint64_t OutSize = Context.getTypeSize(OutTy);
+      uint64_t InSize = Context.getTypeSize(InTy);
+      if (OutSize == InSize)
         continue;
       
-      // If the input and output operands are not mentioned in the asm string,
-      // then we can promote them and the asm string won't notice.  Check this
+      // If the smaller input/output operand is not mentioned in the asm string,
+      // then we can promote it and the asm string won't notice.  Check this
       // case now.
-      bool MentionedInput = false;
-      bool MentionedOutput = false;
+      bool SmallerValueMentioned = false;
       for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
         AsmStmt::AsmStringPiece &Piece = Pieces[p];
         if (!Piece.isOperand()) continue;
-        MentionedInput |= Piece.getOperandNo() == i+NumOutputs;
-        MentionedOutput |= Piece.getOperandNo() == TiedTo;
+        
+        // If this is a reference to the input and if the input was the smaller
+        // one, then we have to reject this asm.
+        if (Piece.getOperandNo() == i+NumOutputs) {
+          if (InSize < OutSize) {
+            SmallerValueMentioned = true;
+            break;
+          }
+        }
+
+        // If this is a reference to the input and if the input was the smaller
+        // one, then we have to reject this asm.
+        if (Piece.getOperandNo() == TiedTo) {
+          if (InSize > OutSize) {
+            SmallerValueMentioned = true;
+            break;
+          }
+        }
       }
       
-      // If neither the input nor the output was mentioned in the asm string,
-      // and if the output was a register, just extend the shorter one to the
-      // size of the larger one.
-      // TODO: if only the larger one is mentioned, we could also support this.
-      if (!MentionedInput && !MentionedOutput &&
+      // If the smaller value wasn't mentioned in the asm string, and if the
+      // output was a register, just extend the shorter one to the size of the
+      // larger one.
+      if (!SmallerValueMentioned &&
           OutputConstraintInfos[TiedTo].allowsRegister())
         continue;
     }
index d7309149ebb6336b96f1d454eb22d05e4e1f13e3..8aa392aa8071b6214d7ef2ba95473dd567cd0ceb 100644 (file)
@@ -69,11 +69,22 @@ unsigned char t12(unsigned input) {
   return output;
 }
 
+unsigned char t13(unsigned input) {
+  unsigned char output;
+  __asm__("xyz %1"
+          : "=a" (output)
+          : "0" (input));
+  return output;
+}
+
 
+// bitfield destination of an asm.
 struct S {
   int a : 4;
 };
 
-void test13(struct S *P) {
+void t14(struct S *P) {
   __asm__("abc %0" : "=r"(P->a) );
 }
+
+