[ms-inline asm] Add constraints to MSAsmStmt.  We don't currently compute
the constraints, so in the interim we speculatively assume a 'r' constraint.
This is expected to work for most cases on x86.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162784 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 2303cb9..042c513 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -1677,6 +1677,7 @@
   unsigned NumAsmToks;
 
   Token *AsmToks;
+  StringRef *Constraints;
   StringRef *Clobbers;
 
 public:
@@ -1684,12 +1685,12 @@
             bool issimple, bool isvolatile, ArrayRef<Token> asmtoks,
             ArrayRef<IdentifierInfo*> inputs, ArrayRef<IdentifierInfo*> outputs,
             ArrayRef<Expr*> inputexprs, ArrayRef<Expr*> outputexprs,
-            StringRef asmstr, ArrayRef<StringRef> clobbers,
-            SourceLocation endloc);
+            StringRef asmstr, ArrayRef<StringRef> constraints, 
+            ArrayRef<StringRef> clobbers, SourceLocation endloc);
 
   /// \brief Build an empty MS-style inline-assembly statement.
   explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty),
-    NumAsmToks(0), AsmToks(0), Clobbers(0) { }
+    NumAsmToks(0), AsmToks(0), Constraints(0), Clobbers(0) { }
 
   SourceLocation getLBraceLoc() const { return LBraceLoc; }
   void setLBraceLoc(SourceLocation L) { LBraceLoc = L; }
@@ -1712,7 +1713,9 @@
 
   //===--- Output operands ---===//
 
-  StringRef getOutputConstraint(unsigned i) const;
+  StringRef getOutputConstraint(unsigned i) const {
+    return Constraints[i];
+  }
 
   Expr *getOutputExpr(unsigned i);
 
@@ -1722,7 +1725,9 @@
 
   //===--- Input operands ---===//
 
-  StringRef getInputConstraint(unsigned i) const;
+  StringRef getInputConstraint(unsigned i) const {
+    return Constraints[i + NumOutputs];
+  }
 
   Expr *getInputExpr(unsigned i);
   void setInputExpr(unsigned i, Expr *E);
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 8462265..ac432e8 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -630,14 +630,6 @@
   return cast<Expr>(Exprs[i]);
 }
 
-/// getOutputConstraint - Return the constraint string for the specified
-/// output operand.  All output constraints are known to be non-empty (either
-/// '=' or '+').
-StringRef MSAsmStmt::getOutputConstraint(unsigned i) const {
-  // FIXME: Compute constraints.
-  return StringRef();
-}
-
 Expr *MSAsmStmt::getInputExpr(unsigned i) {
   return cast<Expr>(Exprs[i + NumOutputs]);
 }
@@ -645,13 +637,6 @@
   Exprs[i + NumOutputs] = E;
 }
 
-/// getInputConstraint - Return the specified input constraint.  Unlike output
-/// constraints, these can be empty.
-StringRef MSAsmStmt::getInputConstraint(unsigned i) const {
-  // FIXME: Compute constraints.
-  return StringRef();
-}
-
 QualType CXXCatchStmt::getCaughtType() const {
   if (ExceptionDecl)
     return ExceptionDecl->getType();
@@ -691,8 +676,8 @@
                      ArrayRef<Token> asmtoks, ArrayRef<IdentifierInfo*> inputs,
                      ArrayRef<IdentifierInfo*> outputs,
                      ArrayRef<Expr*> inputexprs, ArrayRef<Expr*> outputexprs,
-                     StringRef asmstr, ArrayRef<StringRef> clobbers,
-                     SourceLocation endloc)
+                     StringRef asmstr, ArrayRef<StringRef> constraints,
+                     ArrayRef<StringRef> clobbers, SourceLocation endloc)
   : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, outputs.size(), inputs.size(),
             clobbers.size()), LBraceLoc(lbraceloc), EndLoc(endloc),
     AsmStr(asmstr.str()), NumAsmToks(asmtoks.size()) {
@@ -717,6 +702,14 @@
   for (unsigned i = 0, e = NumAsmToks; i != e; ++i)
     AsmToks[i] = asmtoks[i];
 
+  Constraints = new (C) StringRef[NumExprs];
+  for (unsigned i = 0, e = NumExprs; i != e; ++i) {
+    size_t size = constraints[i].size();
+    char *dest = new (C) char[size];
+    std::strncpy(dest, constraints[i].data(), size); 
+    Constraints[i] = StringRef(dest, size);
+  }
+
   Clobbers = new (C) StringRef[NumClobbers];
   for (unsigned i = 0, e = NumClobbers; i != e; ++i) {
     // FIXME: Avoid the allocation/copy if at all possible.
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 638c879..f51e476 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -454,17 +454,20 @@
   return Res.str();
 }
 
-#define DEF_SIMPLE_MSASM                                                   \
-  MSAsmStmt *NS =                                                          \
-    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, \
-                            /*IsVolatile*/ true, AsmToks, Inputs, Outputs, \
-                            InputExprs, OutputExprs, AsmString, Clobbers,  \
-                            EndLoc);
+#define DEF_SIMPLE_MSASM                                                     \
+  MSAsmStmt *NS =                                                            \
+    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,   \
+                            /*IsVolatile*/ true, AsmToks, Inputs, Outputs,   \
+                            InputExprs, OutputExprs, AsmString, Constraints, \
+                            Clobbers, EndLoc);
 
 StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
                                 SourceLocation LBraceLoc,
                                 ArrayRef<Token> AsmToks,
                                 SourceLocation EndLoc) {
+  SmallVector<StringRef, 4> Constraints;
+  std::vector<std::string> InputConstraints;
+  std::vector<std::string> OutputConstraints;
   SmallVector<StringRef,4> Clobbers;
   std::set<std::string> ClobberRegs;
   SmallVector<IdentifierInfo*, 4> Inputs;
@@ -606,9 +609,11 @@
               if (isDef) {
                 Outputs.push_back(II);
                 OutputExprs.push_back(Result.take());
+                OutputConstraints.push_back("=r");
               } else {
                 Inputs.push_back(II);
                 InputExprs.push_back(Result.take());
+                InputConstraints.push_back("r");
               }
             }
           }
@@ -620,10 +625,20 @@
          E = ClobberRegs.end(); I != E; ++I)
     Clobbers.push_back(*I);
 
+  // Merge the output and input constraints.  Output constraints are expected
+  // first.
+  for (std::vector<std::string>::iterator I = OutputConstraints.begin(),
+         E = OutputConstraints.end(); I != E; ++I)
+    Constraints.push_back(*I);
+
+  for (std::vector<std::string>::iterator I = InputConstraints.begin(),
+         E = InputConstraints.end(); I != E; ++I)
+    Constraints.push_back(*I);
+
   MSAsmStmt *NS =
     new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
                             /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
-                            InputExprs, OutputExprs, AsmString, Clobbers,
-                            EndLoc);
+                            InputExprs, OutputExprs, AsmString, Constraints,
+                            Clobbers, EndLoc);
   return Owned(NS);
 }