r212389 - Add support for nested blocks in Microsoft inline assembly

Ehsan Akhgari ehsan.akhgari at gmail.com
Sat Jul 5 22:26:54 PDT 2014


Author: ehsan
Date: Sun Jul  6 00:26:54 2014
New Revision: 212389

URL: http://llvm.org/viewvc/llvm-project?rev=212389&view=rev
Log:
Add support for nested blocks in Microsoft inline assembly

This fixes http://llvm.org/PR20204.

Added:
    cfe/trunk/test/Parser/ms-inline-asm-nested-braces.c
Modified:
    cfe/trunk/lib/Parse/ParseStmtAsm.cpp
    cfe/trunk/test/CodeGen/ms-inline-asm-64.c
    cfe/trunk/test/CodeGen/ms-inline-asm.c
    cfe/trunk/test/Parser/ms-inline-asm.c

Modified: cfe/trunk/lib/Parse/ParseStmtAsm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmtAsm.cpp?rev=212389&r1=212388&r2=212389&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmtAsm.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmtAsm.cpp Sun Jul  6 00:26:54 2014
@@ -322,19 +322,21 @@ StmtResult Parser::ParseMicrosoftAsmStat
   SourceLocation EndLoc = AsmLoc;
   SmallVector<Token, 4> AsmToks;
 
-  bool InBraces = false;
+  unsigned BraceNesting = 0;
   unsigned short savedBraceCount = 0;
   bool InAsmComment = false;
   FileID FID;
   unsigned LineNo = 0;
   unsigned NumTokensRead = 0;
-  SourceLocation LBraceLoc;
+  SmallVector<SourceLocation, 4> LBraceLocs;
+  bool SkippedStartOfLine = false;
 
   if (Tok.is(tok::l_brace)) {
     // Braced inline asm: consume the opening brace.
-    InBraces = true;
+    BraceNesting = 1;
     savedBraceCount = BraceCount;
-    EndLoc = LBraceLoc = ConsumeBrace();
+    EndLoc = ConsumeBrace();
+    LBraceLocs.push_back(EndLoc);
     ++NumTokensRead;
   } else {
     // Single-line inline asm; compute which line it is on.
@@ -342,6 +344,7 @@ StmtResult Parser::ParseMicrosoftAsmStat
         SrcMgr.getDecomposedExpansionLoc(EndLoc);
     FID = ExpAsmLoc.first;
     LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second);
+    LBraceLocs.push_back(SourceLocation());
   }
 
   SourceLocation TokLoc = Tok.getLocation();
@@ -350,17 +353,26 @@ StmtResult Parser::ParseMicrosoftAsmStat
     if (isEofOrEom())
       break;
 
-    if (!InAsmComment && Tok.is(tok::semi)) {
+    if (!InAsmComment && Tok.is(tok::l_brace)) {
+      // Consume the opening brace.
+      SkippedStartOfLine = Tok.isAtStartOfLine();
+      EndLoc = ConsumeBrace();
+      BraceNesting++;
+      LBraceLocs.push_back(EndLoc);
+      TokLoc = Tok.getLocation();
+      ++NumTokensRead;
+      continue;
+    } else if (!InAsmComment && Tok.is(tok::semi)) {
       // A semicolon in an asm is the start of a comment.
       InAsmComment = true;
-      if (InBraces) {
+      if (BraceNesting) {
         // 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 (!InBraces || InAsmComment) {
+    } else if (!BraceNesting || InAsmComment) {
       // If end-of-line is significant, check whether this token is on a
       // new line.
       std::pair<FileID, unsigned> ExpLoc =
@@ -368,7 +380,7 @@ StmtResult Parser::ParseMicrosoftAsmStat
       if (ExpLoc.first != FID ||
           SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
         // If this is a single-line __asm, we're done.
-        if (!InBraces)
+        if (!BraceNesting)
           break;
         // We're no longer in a comment.
         InAsmComment = false;
@@ -379,11 +391,21 @@ StmtResult Parser::ParseMicrosoftAsmStat
         break;
       }
     }
-    if (!InAsmComment && InBraces && Tok.is(tok::r_brace) &&
-        BraceCount == (savedBraceCount + 1)) {
-      // Consume the closing brace, and finish
+    if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) &&
+        BraceCount == (savedBraceCount + BraceNesting)) {
+      // Consume the closing brace.
+      SkippedStartOfLine = Tok.isAtStartOfLine();
       EndLoc = ConsumeBrace();
-      break;
+      BraceNesting--;
+      // Finish if all of the opened braces in the inline asm section were consumed.
+      if (BraceNesting == 0)
+        break;
+      else {
+        LBraceLocs.pop_back();
+        TokLoc = Tok.getLocation();
+        ++NumTokensRead;
+        continue;
+      }
     }
 
     // Consume the next token; make sure we don't modify the brace count etc.
@@ -392,17 +414,25 @@ StmtResult Parser::ParseMicrosoftAsmStat
     if (InAsmComment)
       PP.Lex(Tok);
     else {
+      // Set the token as the start of line if we skipped the original start
+      // of line token in case it was a nested brace.
+      if (SkippedStartOfLine)
+        Tok.setFlag(Token::StartOfLine);
       AsmToks.push_back(Tok);
       ConsumeAnyToken();
     }
     TokLoc = Tok.getLocation();
     ++NumTokensRead;
+    SkippedStartOfLine = false;
   } while (1);
 
-  if (InBraces && BraceCount != savedBraceCount) {
+  if (BraceNesting && BraceCount != savedBraceCount) {
     // __asm without closing brace (this can happen at EOF).
-    Diag(Tok, diag::err_expected) << tok::r_brace;
-    Diag(LBraceLoc, diag::note_matching) << tok::l_brace;
+    for (unsigned i = 0; i < BraceNesting; ++i) {
+      Diag(Tok, diag::err_expected) << tok::r_brace;
+      Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace;
+      LBraceLocs.pop_back();
+    }
     return StmtError();
   } else if (NumTokensRead == 0) {
     // Empty __asm.
@@ -431,10 +461,12 @@ StmtResult Parser::ParseMicrosoftAsmStat
       Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error;
   }
 
+  assert(!LBraceLocs.empty() && "Should have at least one location here");
+
   // If we don't support assembly, or the assembly is empty, we don't
   // need to instantiate the AsmParser, etc.
   if (!TheTarget || AsmToks.empty()) {
-    return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, StringRef(),
+    return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(),
                                   /*NumOutputs*/ 0, /*NumInputs*/ 0,
                                   ConstraintRefs, ClobberRefs, Exprs, EndLoc);
   }
@@ -523,7 +555,7 @@ StmtResult Parser::ParseMicrosoftAsmStat
   }
 
   // FIXME: We should be passing source locations for better diagnostics.
-  return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, AsmStringIR,
+  return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR,
                                 NumOutputs, NumInputs, ConstraintRefs,
                                 ClobberRefs, Exprs, EndLoc);
 }

Modified: cfe/trunk/test/CodeGen/ms-inline-asm-64.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ms-inline-asm-64.c?rev=212389&r1=212388&r2=212389&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/ms-inline-asm-64.c (original)
+++ cfe/trunk/test/CodeGen/ms-inline-asm-64.c Sun Jul  6 00:26:54 2014
@@ -37,7 +37,9 @@ int t4() {
   foo.b = 2;
   __asm {
      lea ebx, foo
-     mov eax, [ebx].foo.a
+     {
+       mov eax, [ebx].foo.a
+     }
      mov [ebx].foo.b, ecx
   }
   return foo.b;

Modified: cfe/trunk/test/CodeGen/ms-inline-asm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ms-inline-asm.c?rev=212389&r1=212388&r2=212389&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/ms-inline-asm.c (original)
+++ cfe/trunk/test/CodeGen/ms-inline-asm.c Sun Jul  6 00:26:54 2014
@@ -52,6 +52,11 @@ void t7() {
   __asm {
     int 0x2c ; } asm comments are fun! }{
   }
+  __asm {
+    {
+      int 0x2c ; } asm comments are fun! }{
+    }
+  }
   __asm {}
 // CHECK: t7
 // CHECK: call void asm sideeffect inteldialect "int $$0x2c", "~{dirflag},~{fpsr},~{flags}"()
@@ -73,8 +78,8 @@ int t8() {
 void t9() {
   __asm {
     push ebx
-    mov ebx, 0x07
-    pop ebx
+    { mov ebx, 0x07 }
+    __asm { pop ebx }
   }
 // CHECK: t9
 // CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"()
@@ -129,7 +134,7 @@ void t14() {
   unsigned i = 1, j = 2;
   __asm {
     .if 1
-    mov eax, i
+    { mov eax, i }
     .else
     mov ebx, j
     .endif

Added: cfe/trunk/test/Parser/ms-inline-asm-nested-braces.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/ms-inline-asm-nested-braces.c?rev=212389&view=auto
==============================================================================
--- cfe/trunk/test/Parser/ms-inline-asm-nested-braces.c (added)
+++ cfe/trunk/test/Parser/ms-inline-asm-nested-braces.c Sun Jul  6 00:26:54 2014
@@ -0,0 +1,9 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -verify -fasm-blocks
+
+int t_fail() { // expected-note {{to match this}}
+  __asm
+  { // expected-note {{to match this}}
+    { // expected-note {{to match this}}
+      {
+      } // expected-error 3 {{expected}}

Modified: cfe/trunk/test/Parser/ms-inline-asm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/ms-inline-asm.c?rev=212389&r1=212388&r2=212389&view=diff
==============================================================================
--- cfe/trunk/test/Parser/ms-inline-asm.c (original)
+++ cfe/trunk/test/Parser/ms-inline-asm.c Sun Jul  6 00:26:54 2014
@@ -34,6 +34,17 @@ void t8() {
 void t9() {
   __asm nop __asm nop ; __asm nop
 }
+void t10() {
+  __asm {
+    mov eax, 0
+    __asm {
+      mov eax, 1
+      {
+        mov eax, 2
+      }
+    }
+  }
+}
 int t_fail() { // expected-note {{to match this}}
   __asm 
   __asm { // expected-error 3 {{expected}} expected-note {{to match this}}





More information about the cfe-commits mailing list