clang-cl: Merge adjacent single-line __asm blocks

Summary:
This patch extends the __asm parser to make it keep parsing input tokens
as inline assembly if a single-line __asm line is followed by another line
starting with __asm too.  It also makes sure that we correctly keep
matching braces in such situations by separating the notions of how many
braces we are matching and whether we are in single-line asm block mode.

Reviewers: rnk

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D4598

llvm-svn: 213916
diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp
index 58d6996..f1d2946 100644
--- a/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/clang/lib/Parse/ParseStmtAsm.cpp
@@ -322,6 +322,7 @@
   SourceLocation EndLoc = AsmLoc;
   SmallVector<Token, 4> AsmToks;
 
+  bool SingleLineMode = true;
   unsigned BraceNesting = 0;
   unsigned short savedBraceCount = BraceCount;
   bool InAsmComment = false;
@@ -333,6 +334,7 @@
 
   if (Tok.is(tok::l_brace)) {
     // Braced inline asm: consume the opening brace.
+    SingleLineMode = false;
     BraceNesting = 1;
     EndLoc = ConsumeBrace();
     LBraceLocs.push_back(EndLoc);
@@ -364,30 +366,39 @@
     } else if (!InAsmComment && Tok.is(tok::semi)) {
       // A semicolon in an asm is the start of a comment.
       InAsmComment = true;
-      if (BraceNesting) {
+      if (!SingleLineMode) {
         // Compute which line the comment is on.
         std::pair<FileID, unsigned> ExpSemiLoc =
             SrcMgr.getDecomposedExpansionLoc(TokLoc);
         FID = ExpSemiLoc.first;
         LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second);
       }
-    } else if (!BraceNesting || InAsmComment) {
+    } else if (SingleLineMode || InAsmComment) {
       // If end-of-line is significant, check whether this token is on a
       // new line.
       std::pair<FileID, unsigned> ExpLoc =
           SrcMgr.getDecomposedExpansionLoc(TokLoc);
       if (ExpLoc.first != FID ||
           SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
-        // If this is a single-line __asm, we're done.
-        if (!BraceNesting)
+        // If this is a single-line __asm, we're done, except if the next
+        // line begins with an __asm too, in which case we finish a comment
+        // if needed and then keep processing the next line as a single
+        // line __asm.
+        bool isAsm = Tok.is(tok::kw_asm);
+        if (SingleLineMode && !isAsm)
           break;
         // We're no longer in a comment.
         InAsmComment = false;
+        if (isAsm) {
+          LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second);
+          SkippedStartOfLine = Tok.isAtStartOfLine();
+        }
       } else if (!InAsmComment && Tok.is(tok::r_brace)) {
-        // Single-line asm always ends when a closing brace is seen.
-        // FIXME: This is compatible with Apple gcc's -fasm-blocks; what
-        // does MSVC do here?
-        break;
+        // In MSVC mode, braces only participate in brace matching and
+        // separating the asm statements.  This is an intentional
+        // departure from the Apple gcc behavior.
+        if (!BraceNesting)
+          break;
       }
     }
     if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) &&
@@ -398,7 +409,7 @@
       BraceNesting--;
       // Finish if all of the opened braces in the inline asm section were
       // consumed.
-      if (BraceNesting == 0)
+      if (BraceNesting == 0 && !SingleLineMode)
         break;
       else {
         LBraceLocs.pop_back();
diff --git a/clang/test/CodeGen/ms-inline-asm.c b/clang/test/CodeGen/ms-inline-asm.c
index 2c67106..cd41d73 100644
--- a/clang/test/CodeGen/ms-inline-asm.c
+++ b/clang/test/CodeGen/ms-inline-asm.c
@@ -10,9 +10,7 @@
 
 void t2() {
 // CHECK: @t2
-// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "nop\0A\09nop\0A\09nop", "~{dirflag},~{fpsr},~{flags}"()
 // CHECK: ret void
   __asm nop
   __asm nop
@@ -28,8 +26,7 @@
 
 void t4(void) {
 // CHECK: @t4
-// CHECK: call void asm sideeffect inteldialect "mov ebx, eax", "~{ebx},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov ecx, ebx", "~{ecx},~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "mov ebx, eax\0A\09mov ecx, ebx", "~{ebx},~{ecx},~{dirflag},~{fpsr},~{flags}"()
 // CHECK: ret void
   __asm mov ebx, eax
   __asm mov ecx, ebx
@@ -69,9 +66,7 @@
   __asm int 4
   return 10;
 // CHECK: t8
-// CHECK: call void asm sideeffect inteldialect "int $$4", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "int $$4", "~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "int $$4\0A\09int $$4", "~{dirflag},~{fpsr},~{flags}"()
 // CHECK: ret i32 10
 }
 
@@ -126,8 +121,7 @@
   __asm movzx eax, i
   __asm movzx eax, j
 // CHECK: t13
-// CHECK: call void asm sideeffect inteldialect "movzx eax, byte ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "movzx eax, word ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i16* %{{.*}})
+// CHECK: call void asm sideeffect inteldialect "movzx eax, byte ptr $0\0A\09movzx eax, word ptr $1", "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j)
 }
 
 void t14() {
@@ -145,14 +139,15 @@
 
 int gvar = 10;
 void t15() {
+// CHECK: t15
   int lvar = 10;
   __asm mov eax, lvar        ; eax = 10
+// CHECK: mov eax, dword ptr $0
   __asm mov eax, offset lvar ; eax = address of lvar
+// CHECK: mov eax, $1
   __asm mov eax, offset gvar ; eax = address of gvar
-// CHECK: t15
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @{{.*}})
+// CHECK: mov eax, $2
+// CHECK: "*m,r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* @{{.*}})
 }
 
 void t16() {
@@ -163,50 +158,52 @@
 }
 
 void t17() {
-  __asm _emit 0x4A
-  __asm _emit 0x43
-  __asm _emit 0x4B
-  __asm _EMIT 0x4B
 // CHECK: t17
-// CHECK:  call void asm sideeffect inteldialect ".byte 0x4A", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK:  call void asm sideeffect inteldialect ".byte 0x43", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK:  call void asm sideeffect inteldialect ".byte 0x4B", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK:  call void asm sideeffect inteldialect ".byte 0x4B", "~{dirflag},~{fpsr},~{flags}"()
+  __asm _emit 0x4A
+// CHECK: .byte 0x4A
+  __asm _emit 0x43
+// CHECK: .byte 0x43
+  __asm _emit 0x4B
+// CHECK: .byte 0x4B
+  __asm _EMIT 0x4B
+// CHECK: .byte 0x4B
+// CHECK:  "~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t20() {
+// CHECK: t20
   char bar;
   int foo;
   char _bar[2];
   int _foo[4];
 
   __asm mov eax, LENGTH foo
+// CHECK: mov eax, $$1
   __asm mov eax, LENGTH bar
+// CHECK: mov eax, $$1
   __asm mov eax, LENGTH _foo
+// CHECK: mov eax, $$4
   __asm mov eax, LENGTH _bar
-// CHECK: t20
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+// CHECK: mov eax, $$2
 
   __asm mov eax, TYPE foo
+// CHECK: mov eax, $$4
   __asm mov eax, TYPE bar
+// CHECK: mov eax, $$1
   __asm mov eax, TYPE _foo
+// CHECK: mov eax, $$4
   __asm mov eax, TYPE _bar
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+// CHECK: mov eax, $$1
 
   __asm mov eax, SIZE foo
+// CHECK: mov eax, $$4
   __asm mov eax, SIZE bar
+// CHECK: mov eax, $$1
   __asm mov eax, SIZE _foo
+// CHECK: mov eax, $$16
   __asm mov eax, SIZE _bar
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$16", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+// CHECK: mov eax, $$2
+// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t21() {
@@ -253,34 +250,35 @@
 }
 
 void t25() {
-  __asm mov eax, 0ffffffffh
-  __asm mov eax, 0fh
-  __asm mov eax, 0a2h
-  __asm mov eax, 0xa2h
-  __asm mov eax, 0xa2
 // CHECK: t25
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4294967295", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$15", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$162", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$0xa2h", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$0xa2", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+  __asm mov eax, 0ffffffffh
+// CHECK: mov eax, $$4294967295
+  __asm mov eax, 0fh
+// CHECK: mov eax, $$15
+  __asm mov eax, 0a2h
+// CHECK: mov eax, $$162
+  __asm mov eax, 0xa2h
+// CHECK: mov eax, $$0xa2h
+  __asm mov eax, 0xa2
+// CHECK: mov eax, $$0xa2
+// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t26() {
-  __asm pushad
-  __asm mov eax, 0
-  __asm __emit 0fh
-  __asm __emit 0a2h
-  __asm __EMIT 0a2h
-  __asm popad
-// FIXME: These all need to be merged into the same asm blob.
 // CHECK: t26
-// CHECK: call void asm sideeffect inteldialect "pushad", "~{esp},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$0", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect ".byte 0fh", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect ".byte 0a2h", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect ".byte 0a2h", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "popad", "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"()
+  __asm pushad
+// CHECK: pushad
+  __asm mov eax, 0
+// CHECK: mov eax, $$0
+  __asm __emit 0fh
+// CHECK: .byte 0fh
+  __asm __emit 0a2h
+// CHECK: .byte 0a2h
+  __asm __EMIT 0a2h
+// CHECK: .byte 0a2h
+  __asm popad
+// CHECK: popad
+// CHECK: "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t27() {
@@ -290,160 +288,171 @@
 }
 
 void t28() {
-  __asm align 8
-  __asm align 16;
-  __asm align 128;
-  __asm ALIGN 256;
 // CHECK: t28
-// CHECK: call void asm sideeffect inteldialect ".align 3", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect ".align 4", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect ".align 7", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect ".align 8", "~{dirflag},~{fpsr},~{flags}"()
+  __asm align 8
+// CHECK: .align 3
+  __asm align 16;
+// CHECK: .align 4
+  __asm align 128;
+// CHECK: .align 7
+  __asm ALIGN 256;
+// CHECK: .align 8
+// CHECK: "~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t29() {
+// CHECK: t29
   int arr[2] = {0, 0};
   int olen = 0, osize = 0, otype = 0;
   __asm mov olen, LENGTH arr
+// CHECK: mov dword ptr $0, $$2
   __asm mov osize, SIZE arr
+// CHECK: mov dword ptr $1, $$8
   __asm mov otype, TYPE arr
-// CHECK: t29
-// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, $$2", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, $$8", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, $$4", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
+// CHECK: mov dword ptr $2, $$4
+// CHECK: "=*m,=*m,=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}})
 }
 
 int results[2] = {13, 37};
 int *t30()
+// CHECK: t30
 {
   int *res;
   __asm lea edi, results
+// CHECK: lea edi, dword ptr $1
   __asm mov res, edi
+// CHECK: mov dword ptr $0, edi
   return res;
-// CHECK: t30
-// CHECK: call void asm sideeffect inteldialect "lea edi, dword ptr $0", "*m,~{edi},~{dirflag},~{fpsr},~{flags}"([2 x i32]* @{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, edi", "=*m,~{dirflag},~{fpsr},~{flags}"(i32** %{{.*}})
+// CHECK: "=*m,*m,~{edi},~{dirflag},~{fpsr},~{flags}"(i32** %{{.*}}, [2 x i32]* @{{.*}})
 }
 
 void t31() {
-  __asm pushad
-  __asm popad
 // CHECK: t31
-// CHECK: call void asm sideeffect inteldialect "pushad", "~{esp},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "popad", "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"()
+  __asm pushad
+// CHECK: pushad
+  __asm popad
+// CHECK: popad
+// CHECK: "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t32() {
+// CHECK: t32
   int i;
   __asm mov eax, i
+// CHECK: mov eax, dword ptr $0
   __asm mov eax, dword ptr i
+// CHECK: mov eax, dword ptr $1
   __asm mov ax, word ptr i
+// CHECK: mov ax, word ptr $2
   __asm mov al, byte ptr i
-// CHECK: t32
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov ax, word ptr $0", "*m,~{ax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov al, byte ptr $0", "*m,~{al},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
+// CHECK: mov al, byte ptr $3
+// CHECK: "*m,*m,*m,*m,~{al},~{ax},~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}})
 }
 
 void t33() {
+// CHECK: t33
   int i;
   __asm mov eax, [i]
+// CHECK: mov eax, dword ptr $0
   __asm mov eax, dword ptr [i]
+// CHECK: mov eax, dword ptr $1
   __asm mov ax, word ptr [i]
+// CHECK: mov ax, word ptr $2
   __asm mov al, byte ptr [i]
-// CHECK: t33
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov ax, word ptr $0", "*m,~{ax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
-// CHECK: call void asm sideeffect inteldialect "mov al, byte ptr $0", "*m,~{al},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}})
+// CHECK: mov al, byte ptr $3
+// CHECK: "*m,*m,*m,*m,~{al},~{ax},~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}})
 }
 
 void t34() {
-  __asm prefetchnta 64[eax]
-  __asm mov eax, dword ptr 4[eax]
 // CHECK: t34
-// CHECK: call void asm sideeffect inteldialect "prefetchnta $$64[eax]", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4[eax]", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+  __asm prefetchnta 64[eax]
+// CHECK: prefetchnta $$64[eax]
+  __asm mov eax, dword ptr 4[eax]
+// CHECK: mov eax, dword ptr $$4[eax]
+// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t35() {
-  __asm prefetchnta [eax + (200*64)]
-  __asm mov eax, dword ptr [eax + (200*64)]
 // CHECK: t35
-// CHECK: call void asm sideeffect inteldialect "prefetchnta [eax + ($$200*$$64)]", "~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr [eax + ($$200*$$64)]", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+  __asm prefetchnta [eax + (200*64)]
+// CHECK: prefetchnta [eax + ($$200*$$64)]
+  __asm mov eax, dword ptr [eax + (200*64)]
+// CHECK: mov eax, dword ptr [eax + ($$200*$$64)]
+// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t36() {
-  int arr[4];
-  __asm mov eax, 4[arr]
-  __asm mov eax, 4[arr + 4]
-  __asm mov eax, 8[arr + 4 + 32*2 - 4]
-  __asm mov eax, 12[4 + arr]
-  __asm mov eax, 4[4 + arr + 4]
-  __asm mov eax, 4[64 + arr + (2*32)]
-  __asm mov eax, 4[64 + arr - 2*32]
-  __asm mov eax, [arr + 4]
-  __asm mov eax, [arr + 4 + 32*2 - 4]
-  __asm mov eax, [4 + arr]
-  __asm mov eax, [4 + arr + 4]
-  __asm mov eax, [64 + arr + (2*32)]
-  __asm mov eax, [64 + arr - 2*32]
 // CHECK: t36
+  int arr[4];
+  // Work around PR20368: These should be single line blocks
+  __asm { mov eax, 4[arr] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 4[arr + 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 8[arr + 4 + 32*2 - 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 12[4 + arr] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 4[4 + arr + 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 4[64 + arr + (2*32)] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 4[64 + arr - 2*32] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, [arr + 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, [arr + 4 + 32*2 - 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, [4 + arr] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, [4 + arr + 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, [64 + arr + (2*32)] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, [64 + arr - 2*32] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
 }
 
 void t37() {
-  __asm mov eax, 4 + 8
-  __asm mov eax, 4 + 8 * 16
-  __asm mov eax, -4 + 8 * 16
-  __asm mov eax, (4 + 4) * 16
-  __asm mov eax, 4 + 8 * -16
-  __asm mov eax, 4 + 16 / -8
-  __asm mov eax, (16 + 16) / -8
-  __asm mov eax, ~15
 // CHECK: t37
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$12", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$132", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$124", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$128", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4294967172", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4294967292", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4294967280", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+  __asm mov eax, 4 + 8
+// CHECK: mov eax, $$12
+  __asm mov eax, 4 + 8 * 16
+// CHECK: mov eax, $$132
+  __asm mov eax, -4 + 8 * 16
+// CHECK: mov eax, $$124
+  __asm mov eax, (4 + 4) * 16
+// CHECK: mov eax, $$128
+  __asm mov eax, 4 + 8 * -16
+// CHECK: mov eax, $$4294967172
+  __asm mov eax, 4 + 16 / -8
+// CHECK: mov eax, $$2
+  __asm mov eax, (16 + 16) / -8
+// CHECK: mov eax, $$4294967292
+  __asm mov eax, ~15
+// CHECK: mov eax, $$4294967280
+// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t38() {
-  int arr[4];
-  __asm mov eax, 4+4[arr]
-  __asm mov eax, (4+4)[arr + 4]
-  __asm mov eax, 8*2[arr + 4 + 32*2 - 4]
-  __asm mov eax, 12+20[4 + arr]
-  __asm mov eax, 4*16+4[4 + arr + 4]
-  __asm mov eax, 4*4[64 + arr + (2*32)]
-  __asm mov eax, 4*(4-2)[64 + arr - 2*32]
-  __asm mov eax, 32*(4-2)[arr - 2*32]
 // CHECK: t38
+  int arr[4];
+  // Work around PR20368: These should be single line blocks
+  __asm { mov eax, 4+4[arr] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, (4+4)[arr + 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 8*2[arr + 4 + 32*2 - 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$80$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 12+20[4 + arr] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$36$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 4*16+4[4 + arr + 4] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$76$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 4*4[64 + arr + (2*32)] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$144$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 4*(4-2)[64 + arr - 2*32] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
+  __asm { mov eax, 32*(4-2)[arr - 2*32] }
 // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$0$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}})
 }
 
@@ -459,38 +468,39 @@
 } A;
 
 void t39() {
+// CHECK-LABEL: define void @t39
   __asm mov eax, [eax].A.b
+// CHECK: mov eax, [eax].4
   __asm mov eax, [eax] A.b
+// CHECK: mov eax, [eax] .4
   __asm mov eax, fs:[0] A.b
-  // CHECK-LABEL: define void @t39
-  // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-  // CHECK: call void asm sideeffect inteldialect "mov eax, [eax] .4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
-  // CHECK: call void asm sideeffect inteldialect "mov eax, fs:[$$0] .4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+// CHECK: mov eax, fs:[$$0] .4
+// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t40(float a) {
+// CHECK-LABEL: define void @t40
   int i;
   __asm fld a
+// CHECK: fld dword ptr $1
   __asm fistp i
-  // CHECK-LABEL: define void @t40
-  // CHECK: call void asm sideeffect inteldialect "fld dword ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(float* {{.*}})
-  // CHECK: call void asm sideeffect inteldialect "fistp dword ptr $0", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* {{.*}})
+// CHECK: fistp dword ptr $0
+// CHECK: "=*m,*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, float* %{{.*}})
 }
 
 void t41(unsigned short a) {
+// CHECK-LABEL: define void @t41(i16 zeroext %a)
   __asm mov cs, a;
+// CHECK: mov cs, word ptr $0
   __asm mov ds, a;
+// CHECK: mov ds, word ptr $1
   __asm mov es, a;
+// CHECK: mov es, word ptr $2
   __asm mov fs, a;
+// CHECK: mov fs, word ptr $3
   __asm mov gs, a;
+// CHECK: mov gs, word ptr $4
   __asm mov ss, a;
-  // CHECK-LABEL: define void @t41(i16 zeroext %a)
-  // CHECK: [[T41_A_ADDR:%.+]] = alloca i16
-  // CHECK: store i16 %a, i16* [[T41_A_ADDR]]
-  // CHECK: call void asm sideeffect inteldialect "mov cs, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]])
-  // CHECK: call void asm sideeffect inteldialect "mov ds, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]])
-  // CHECK: call void asm sideeffect inteldialect "mov es, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]])
-  // CHECK: call void asm sideeffect inteldialect "mov fs, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]])
-  // CHECK: call void asm sideeffect inteldialect "mov gs, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]])
-  // CHECK: call void asm sideeffect inteldialect "mov ss, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]])
+// CHECK: mov ss, word ptr $5
+// CHECK: "*m,*m,*m,*m,*m,*m,~{dirflag},~{fpsr},~{flags}"(i16* %a.addr, i16* %a.addr, i16* %a.addr, i16* %a.addr, i16* %a.addr, i16* %a.addr)
 }
diff --git a/clang/test/CodeGen/ms-inline-asm.cpp b/clang/test/CodeGen/ms-inline-asm.cpp
index 83fe107..aaeb454 100644
--- a/clang/test/CodeGen/ms-inline-asm.cpp
+++ b/clang/test/CodeGen/ms-inline-asm.cpp
@@ -22,11 +22,7 @@
   __asm mov eax, dword ptr [Foo :: ptr]
   __asm mov eax, dword ptr [Foo :: ptr]
 // CHECK: @_Z2t1v
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE)
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3Bar3ptrE)
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE)
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE)
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE)
+// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0\0A\09mov eax, dword ptr $1\0A\09mov eax, dword ptr $2\0A\09mov eax, dword ptr $3\0A\09mov eax, dword ptr $4", "*m,*m,*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE)
 }
 
 int gvar = 10;
@@ -35,38 +31,26 @@
   __asm mov eax, offset Foo::ptr
   __asm mov eax, offset Foo::Bar::ptr
 // CHECK: t2
-// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE)
-// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3Bar3ptrE)
+// CHECK: call void asm sideeffect inteldialect "mov eax, $0\0A\09mov eax, $1", "r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE)
 }
 
 // CHECK-LABEL: define void @_Z2t3v()
 void t3() {
   __asm mov eax, LENGTH Foo::ptr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, LENGTH Foo::Bar::ptr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, LENGTH Foo::arr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, LENGTH Foo::Bar::arr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"()
 
   __asm mov eax, TYPE Foo::ptr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, TYPE Foo::Bar::ptr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, TYPE Foo::arr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, TYPE Foo::Bar::arr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"()
 
   __asm mov eax, SIZE Foo::ptr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, SIZE Foo::Bar::ptr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, SIZE Foo::arr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$16", "~{eax},~{dirflag},~{fpsr},~{flags}"()
   __asm mov eax, SIZE Foo::Bar::arr
-// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "mov eax, $$1\0A\09mov eax, $$1\0A\09mov eax, $$4\0A\09mov eax, $$2\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$1\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$16\0A\09mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"()
 
 }
 
@@ -82,9 +66,8 @@
 // CHECK: [[THIS:%.*]] = load [[T4]]** [[T0]]
 // CHECK: [[X:%.*]] = getelementptr inbounds [[T4]]* [[THIS]], i32 0, i32 0
   __asm mov eax, x;
-// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* [[X]])
   __asm mov y, eax;
-// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, eax", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE)
+// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $1\0A\09mov dword ptr $0, eax", "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE, i32* %x)
 }
 
 template <class T> struct T5 {
@@ -97,11 +80,9 @@
   // CHECK: [[Y:%.*]] = alloca i32
   int x, y;
   __asm push y
-  // CHECK: call void asm sideeffect inteldialect "push dword ptr $0", "=*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* [[Y]])
   __asm call T5<int>::create<float>
-  // CHECK: call void asm sideeffect inteldialect "call $0", "r,~{dirflag},~{fpsr},~{flags}"(i32 (float)* @_ZN2T5IiE6createIfEEiT_)
   __asm mov x, eax
-  // CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, eax", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* [[X]])
+  // CHECK: call void asm sideeffect inteldialect "push dword ptr $0\0A\09call $2\0A\09mov dword ptr $1, eax", "=*m,=*m,r,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %y, i32* %x, i32 (float)* @_ZN2T5IiE6createIfEEiT_)
 }
 
 // Just verify this doesn't emit an error.
diff --git a/clang/test/Parser/ms-inline-asm.c b/clang/test/Parser/ms-inline-asm.c
index 00508f5..646f547 100644
--- a/clang/test/Parser/ms-inline-asm.c
+++ b/clang/test/Parser/ms-inline-asm.c
@@ -50,4 +50,4 @@
 }
 int t_fail() { // expected-note {{to match this}}
   __asm 
-  __asm { // expected-error 3 {{expected}} expected-note {{to match this}}
+  __asm { // expected-error 2 {{expected}} expected-note {{to match this}}
diff --git a/clang/test/Sema/ms-inline-asm.c b/clang/test/Sema/ms-inline-asm.c
index 66504aa..e1d79c1 100644
--- a/clang/test/Sema/ms-inline-asm.c
+++ b/clang/test/Sema/ms-inline-asm.c
@@ -60,13 +60,13 @@
   }
 
   // expected-error@+1 {{cannot use base register with variable reference}}
-  __asm mov eax, arr[ebp + 1 + (2 * 5) - 3 + 1<<1]
+  __asm { mov eax, arr[ebp + 1 + (2 * 5) - 3 + 1<<1] }
   // expected-error@+1 {{cannot use index register with variable reference}}
-  __asm mov eax, arr[esi * 4]
+  __asm { mov eax, arr[esi * 4] }
   // expected-error@+1 {{cannot use more than one symbol in memory operand}}
-  __asm mov eax, arr[i]
+  __asm { mov eax, arr[i] }
   // expected-error@+1 {{cannot use more than one symbol in memory operand}}
-  __asm mov eax, global[i]
+  __asm { mov eax, global[i] }
 
   // FIXME: Why don't we diagnose this?
   // expected-Xerror@+1 {{cannot reference multiple local variables in assembly operand}}
@@ -80,22 +80,22 @@
 } A;
 
 void t3() {
-  __asm mov eax, [eax] UndeclaredId // expected-error {{unknown token in expression}}
+  __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}}
 
   // FIXME: Only emit one diagnostic here.
   // expected-error@+2 {{unexpected type name 'A': expected expression}}
   // expected-error@+1 {{unknown token in expression}}
-  __asm mov eax, [eax] A
+  __asm { mov eax, [eax] A }
 }
 
 void t4() {
   // The dot in the "intel dot operator" is optional in MSVC.  MSVC also does
   // global field lookup, but we don't.
-  __asm mov eax, [0] A.a
-  __asm mov eax, [0].A.a
-  __asm mov eax, [0].a    // expected-error {{Unable to lookup field reference!}}
-  __asm mov eax, fs:[0] A.a
-  __asm mov eax, fs:[0].A.a
-  __asm mov eax, fs:[0].a // expected-error {{Unable to lookup field reference!}}
-  __asm mov eax, fs:[0]. A.a  // expected-error {{Unexpected token type!}}
+  __asm { mov eax, [0] A.a }
+  __asm { mov eax, [0].A.a }
+  __asm { mov eax, [0].a } // expected-error {{Unable to lookup field reference!}}
+  __asm { mov eax, fs:[0] A.a }
+  __asm { mov eax, fs:[0].A.a }
+  __asm { mov eax, fs:[0].a } // expected-error {{Unable to lookup field reference!}}
+  __asm { mov eax, fs:[0]. A.a } // expected-error {{Unexpected token type!}}
 }