[cfe-commits] r161780 - in /cfe/trunk: lib/Sema/SemaStmt.cpp test/CodeGen/ms-inline-asm.c

Chad Rosier mcrosier at apple.com
Mon Aug 13 13:32:07 PDT 2012


Author: mcrosier
Date: Mon Aug 13 15:32:07 2012
New Revision: 161780

URL: http://llvm.org/viewvc/llvm-project?rev=161780&view=rev
Log:
[ms-inline asm] Have patchMSAsmStrings() return a vector or AsmStrings.

The AsmParser expects a single asm instruction, but valid ms-style inline asm
statements may contain  multiple instructions.

This happens with asm blocks

__asm {
  mov ebx, eax
  mov ecx, ebx
}

or when multiple asm statements are adjacent to one another

__asm mov ebx, eax
__asm mov ecx, ebx

and

__asm mov ebx, eax __asm mov ecx, ebx

Currently, asm blocks are not properly handled.

Modified:
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/CodeGen/ms-inline-asm.c

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=161780&r1=161779&r2=161780&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Mon Aug 13 15:32:07 2012
@@ -2794,60 +2794,71 @@
   return true;
 }
 
-static std::string PatchMSAsmString(Sema &SemaRef, bool &IsSimple,
-                                    SourceLocation AsmLoc,
-                                    ArrayRef<Token> AsmToks,
-                                    const TargetInfo &TI) {
+static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple,
+                              SourceLocation AsmLoc,
+                              ArrayRef<Token> AsmToks,
+                              ArrayRef<unsigned> LineEnds,
+                              const TargetInfo &TI,
+                              std::vector<std::string> &AsmStrings) {
   assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
-  std::string Res;
-  IdentifierInfo *II = AsmToks[0].getIdentifierInfo();
-  Res = II->getName().str();
 
   // Assume simple asm stmt until we parse a non-register identifer.
   IsSimple = true;
 
-  // Check the operands.
-  for (unsigned i = 1, e = AsmToks.size(); i != e; ++i) {
-    if (needSpaceAsmToken(AsmToks[i]))
-        Res += " ";
-
-    switch (AsmToks[i].getKind()) {
-    default:
-      //llvm_unreachable("Unknown token.");
-      break;
-    case tok::comma: Res += ","; break;
-    case tok::colon: Res += ":"; break;
-    case tok::l_square: Res += "["; break;
-    case tok::r_square: Res += "]"; break;
-    case tok::l_brace: Res += "{"; break;
-    case tok::r_brace: Res += "}"; break;
-    case tok::numeric_constant: {
-      SmallString<32> TokenBuf;
-      TokenBuf.resize(32);
-      bool StringInvalid = false;
-      const char *ThisTokBuf = &TokenBuf[0];
-      unsigned ThisTokLen =
-        Lexer::getSpelling(AsmToks[i], ThisTokBuf, SemaRef.getSourceManager(),
-                           SemaRef.getLangOpts(), &StringInvalid);
-      Res += StringRef(ThisTokBuf, ThisTokLen);
-      break;
-    }
-    case tok::identifier: {
-      II = AsmToks[i].getIdentifierInfo();
-      StringRef Name = II->getName();
-
-      // Valid registers don't need modification.
-      if (TI.isValidGCCRegisterName(Name)) {
-        Res += Name;
+  for (unsigned i = 0, e = LineEnds.size(); i != e; ++i) {
+    SmallString<512> Asm;
+
+    // Check the operands.
+    for (unsigned j = (i == 0) ? 0 : LineEnds[i-1], e = LineEnds[i]; j != e; ++j) {
+
+      IdentifierInfo *II;
+      if (j == 0 || (i > 0 && j == LineEnds[i-1])) {
+        II = AsmToks[j].getIdentifierInfo();
+        Asm = II->getName().str();
+        continue;
+      }
+
+      if (needSpaceAsmToken(AsmToks[j]))
+        Asm += " ";
+
+      switch (AsmToks[j].getKind()) {
+      default:
+        //llvm_unreachable("Unknown token.");
+        break;
+      case tok::comma: Asm += ","; break;
+      case tok::colon: Asm += ":"; break;
+      case tok::l_square: Asm += "["; break;
+      case tok::r_square: Asm += "]"; break;
+      case tok::l_brace: Asm += "{"; break;
+      case tok::r_brace: Asm += "}"; break;
+      case tok::numeric_constant: {
+        SmallString<32> TokenBuf;
+        TokenBuf.resize(32);
+        bool StringInvalid = false;
+        const char *ThisTokBuf = &TokenBuf[0];
+        unsigned ThisTokLen =
+          Lexer::getSpelling(AsmToks[j], ThisTokBuf, SemaRef.getSourceManager(),
+                             SemaRef.getLangOpts(), &StringInvalid);
+        Asm += StringRef(ThisTokBuf, ThisTokLen);
         break;
       }
+      case tok::identifier: {
+        II = AsmToks[j].getIdentifierInfo();
+        StringRef Name = II->getName();
+
+        // Valid registers don't need modification.
+        if (TI.isValidGCCRegisterName(Name)) {
+          Asm += Name;
+          break;
+        }
 
-      // TODO: Lookup the identifier.
-      IsSimple = false;
+        // TODO: Lookup the identifier.
+        IsSimple = false;
+      }
+      } // AsmToks[i].getKind()
     }
-    } // AsmToks[i].getKind()
+    AsmStrings[i] = Asm.c_str();
   }
-  return Res;
 }
 
 // Build the unmodified MSAsmString.
@@ -2898,11 +2909,14 @@
   std::string AsmString = buildMSAsmString(*this, AsmToks, LineEnds);
 
   bool IsSimple;
+  std::vector<std::string> PatchedAsmStrings;
+  PatchedAsmStrings.resize(LineEnds.size());
+
   // Rewrite operands to appease the AsmParser.
-  std::string PatchedAsmString =
-    PatchMSAsmString(*this, IsSimple, AsmLoc, AsmToks, Context.getTargetInfo());
+  patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks, LineEnds, 
+                   Context.getTargetInfo(), PatchedAsmStrings);
 
-  // PatchMSAsmString doesn't correctly patch non-simple asm statements.
+  // patchMSAsmStrings doesn't correctly patch non-simple asm statements.
   if (!IsSimple) {
     MSAsmStmt *NS =
       new (Context) MSAsmStmt(Context, AsmLoc, /* IsSimple */ true,
@@ -2921,29 +2935,32 @@
   const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
   const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));
 
-  llvm::SourceMgr SrcMgr;
-  llvm::MemoryBuffer *Buffer =
-    llvm::MemoryBuffer::getMemBuffer(PatchedAsmString, "<inline asm>");
-
-  // Tell SrcMgr about this buffer, which is what the parser will pick up.
-  SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
-
   OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
   OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
   OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
-  llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
   OwningPtr<llvm::MCSubtargetInfo>
     STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
 
-  OwningPtr<llvm::MCStreamer> Str;
-  OwningPtr<llvm::MCAsmParser>
-    Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
-  OwningPtr<llvm::MCTargetAsmParser>
-    TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
-
-  // Change to the Intel dialect.
-  Parser->setAssemblerDialect(1);
-  Parser->setTargetParser(*TargetParser.get());
+  for (unsigned i = 0, e = PatchedAsmStrings.size(); i != e; ++i) {
+    llvm::SourceMgr SrcMgr;
+    llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
+    llvm::MemoryBuffer *Buffer =
+      llvm::MemoryBuffer::getMemBuffer(PatchedAsmStrings[i], "<inline asm>");
+
+    // Tell SrcMgr about this buffer, which is what the parser will pick up.
+    SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
+
+    OwningPtr<llvm::MCStreamer> Str;
+    OwningPtr<llvm::MCAsmParser>
+      Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
+    OwningPtr<llvm::MCTargetAsmParser>
+      TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
+    // Change to the Intel dialect.
+    Parser->setAssemblerDialect(1);
+    Parser->setTargetParser(*TargetParser.get());
+
+    // TODO: Start parsing.
+  }
 
   MSAsmStmt *NS =
     new (Context) MSAsmStmt(Context, AsmLoc, IsSimple, /* IsVolatile */ true,

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=161780&r1=161779&r2=161780&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/ms-inline-asm.c (original)
+++ cfe/trunk/test/CodeGen/ms-inline-asm.c Mon Aug 13 15:32:07 2012
@@ -6,3 +6,35 @@
 // CHECK: ret void
   __asm {}
 }
+
+void t2() {
+// CHECK: @t2
+// CHECK: call void asm sideeffect "nop\0Anop\0Anop", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: ret void
+  __asm nop
+  __asm nop
+  __asm nop
+}
+
+void t3() {
+// CHECK: @t3
+// CHECK: call void asm sideeffect "nop\0Anop\0Anop", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: ret void
+  __asm nop __asm nop __asm nop
+}
+
+void t4(void) {
+// CHECK: @t4
+// CHECK: call void asm sideeffect "mov ebx, eax\0Amov ecx, ebx", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: ret void
+  __asm mov ebx, eax
+  __asm mov ecx, ebx
+}
+
+void t5(void) {
+// CHECK: @t5
+// CHECK: call void asm sideeffect "mov ebx, eax\0Amov ecx, ebx", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: ret void
+  __asm mov ebx, eax __asm mov ecx, ebx
+}
+





More information about the cfe-commits mailing list