[ms-inline asm] Start tracking which tokens are registers and which are
variables, function or label references.  The former is a potential clobber.
The latter is either an input or an output.  Unfortunately, it's difficult to
test this patch at the moment, but the added test case will eventually do so.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162026 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index b14c7c4..5bd5c8a 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -28,6 +28,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
@@ -2767,6 +2768,8 @@
                               SourceLocation AsmLoc,
                               ArrayRef<Token> AsmToks,
                               const TargetInfo &TI,
+                              std::vector<llvm::BitVector> &AsmRegs,
+                              std::vector<llvm::BitVector> &AsmNames,
                               std::vector<std::string> &AsmStrings) {
   assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
 
@@ -2792,6 +2795,8 @@
 
     // Start a new asm string with the opcode.
     if (isNewAsm) {
+      AsmRegs[NumAsmStrings].resize(AsmToks.size());
+      AsmNames[NumAsmStrings].resize(AsmToks.size());
       Asm = AsmToks[i].getIdentifierInfo()->getName().str();
       continue;
     }
@@ -2821,14 +2826,28 @@
     case tok::identifier: {
       StringRef Name = AsmToks[i].getIdentifierInfo()->getName();
 
-      // Valid registers don't need modification.
+      // Valid register?
       if (TI.isValidGCCRegisterName(Name)) {
+        AsmRegs[NumAsmStrings].set(i);
         Asm += Name;
         break;
       }
 
-      // TODO: Lookup the identifier.
       IsSimple = false;
+
+      // FIXME: Why are we missing this segment register?
+      if (Name == "fs") {
+        Asm += Name;
+        break;
+      }
+
+      // Not a register, so this must be a variable, function or label
+      // reference.  Track these as they are either an Input or an Output.
+      // Unfortunately, we don't know which is which until after we feed
+      // the patched asms to the AsmParser.
+      AsmNames[NumAsmStrings].set(i);
+
+      // TODO: Lookup the identifier and patch appropriately.
       break;
     }
     } // AsmToks[i].getKind()
@@ -2897,12 +2916,17 @@
   std::string AsmString = buildMSAsmString(*this, AsmToks, NumAsmStrings);
 
   bool IsSimple;
+  std::vector<llvm::BitVector> Regs;
+  std::vector<llvm::BitVector> Names;
   std::vector<std::string> PatchedAsmStrings;
+
+  Regs.resize(NumAsmStrings);
+  Names.resize(NumAsmStrings);
   PatchedAsmStrings.resize(NumAsmStrings);
 
   // Rewrite operands to appease the AsmParser.
-  patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks, Context.getTargetInfo(),
-                    PatchedAsmStrings);
+  patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks,
+                    Context.getTargetInfo(), Regs, Names, PatchedAsmStrings);
 
   // patchMSAsmStrings doesn't correctly patch non-simple asm statements.
   if (!IsSimple) {
diff --git a/test/CodeGen/ms-inline-asm.c b/test/CodeGen/ms-inline-asm.c
index ee4ca01..43ecbe3 100644
--- a/test/CodeGen/ms-inline-asm.c
+++ b/test/CodeGen/ms-inline-asm.c
@@ -82,3 +82,20 @@
 // CHECK: t10
 // CHECK: call void asm sideeffect "push ebx\0Amov ebx, 0x07\0Apop ebx", "~{ebx},~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
 }
+
+unsigned t11(void) {
+  unsigned i = 1, j;
+  __asm {
+    mov eax, i
+    mov j, eax
+  }
+  return j;
+// CHECK: t11
+// CHECK: entry:
+// CHECK: [[I:%[a-zA-Z0-9]+]] = alloca i32, align 4
+// CHECK: [[J:%[a-zA-Z0-9]+]] = alloca i32, align 4
+// CHECK: store i32 1, i32* [[I]], align 4
+// CHECK: call void asm sideeffect "mov eax, i\0Amov j, eax", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: [[RET:%[a-zA-Z0-9]+]] = load i32* [[J]], align 4
+// CHECK: ret i32 [[RET]]
+}