Forráskód Böngészése

Etch out the code path for MS-style inline assembly.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158325 91177308-0d34-0410-b5e6-96231b3b80d8
Chad Rosier 13 éve
szülő
commit
8cd64b4c55

+ 4 - 0
include/clang-c/Index.h

@@ -1996,6 +1996,10 @@ enum CXCursorKind {
    */
    */
   CXCursor_SEHFinallyStmt                = 228,
   CXCursor_SEHFinallyStmt                = 228,
 
 
+  /** \brief A MS inline assembly statement extension.
+   */
+  CXCursor_MSAsmStmt                     = 229,
+
   /** \brief The null satement ";": C99 6.8.3p3.
   /** \brief The null satement ";": C99 6.8.3p3.
    *
    *
    * This cursor kind is used to describe the null statement.
    * This cursor kind is used to describe the null statement.

+ 5 - 0
include/clang/AST/RecursiveASTVisitor.h

@@ -1826,6 +1826,11 @@ DEF_TRAVERSE_STMT(AsmStmt, {
     // children() iterates over inputExpr and outputExpr.
     // children() iterates over inputExpr and outputExpr.
   })
   })
 
 
+DEF_TRAVERSE_STMT(MSAsmStmt, { 
+    // FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc.  Once
+    // added this needs to be implemented.
+  })
+
 DEF_TRAVERSE_STMT(CXXCatchStmt, {
 DEF_TRAVERSE_STMT(CXXCatchStmt, {
     TRY_TO(TraverseDecl(S->getExceptionDecl()));
     TRY_TO(TraverseDecl(S->getExceptionDecl()));
     // children() iterates over the handler block.
     // children() iterates over the handler block.

+ 46 - 0
include/clang/AST/Stmt.h

@@ -1606,6 +1606,52 @@ public:
   }
   }
 };
 };
 
 
+/// MSAsmStmt - This represents a MS inline-assembly statement extension.
+///
+class MSAsmStmt : public Stmt {
+  SourceLocation AsmLoc, EndLoc;
+  std::string AsmStr;
+
+  bool IsSimple;
+  bool IsVolatile;
+
+  Stmt **Exprs;
+
+public:
+  MSAsmStmt(ASTContext &C, SourceLocation asmloc, std::string &asmstr,
+            SourceLocation endloc);
+
+  SourceLocation getAsmLoc() const { return AsmLoc; }
+  void setAsmLoc(SourceLocation L) { AsmLoc = L; }
+  SourceLocation getEndLoc() const { return EndLoc; }
+  void setEndLoc(SourceLocation L) { EndLoc = L; }
+
+  bool isVolatile() const { return IsVolatile; }
+  void setVolatile(bool V) { IsVolatile = V; }
+  bool isSimple() const { return IsSimple; }
+  void setSimple(bool V) { IsSimple = V; }
+
+  //===--- Asm String Analysis ---===//
+
+  const std::string *getAsmString() const { return &AsmStr; }
+  std::string *getAsmString() { return &AsmStr; }
+  void setAsmString(StringRef &E) { AsmStr = E.str(); }
+
+  //===--- Other ---===//
+
+  SourceRange getSourceRange() const LLVM_READONLY {
+    return SourceRange(AsmLoc, EndLoc);
+  }
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == MSAsmStmtClass;
+  }
+  static bool classof(const MSAsmStmt *) { return true; }
+
+  child_range children() {
+    return child_range(&Exprs[0], &Exprs[0]);
+  }
+};
+
 class SEHExceptStmt : public Stmt {
 class SEHExceptStmt : public Stmt {
   SourceLocation  Loc;
   SourceLocation  Loc;
   Stmt           *Children[2];
   Stmt           *Children[2];

+ 3 - 0
include/clang/Basic/StmtNodes.td

@@ -31,6 +31,9 @@ def DefaultStmt : DStmt<SwitchCase>;
 // GNU Extensions
 // GNU Extensions
 def AsmStmt : Stmt;
 def AsmStmt : Stmt;
 
 
+// MS Extensions
+def MSAsmStmt : Stmt;
+
 // Obj-C statements
 // Obj-C statements
 def ObjCAtTryStmt : Stmt;
 def ObjCAtTryStmt : Stmt;
 def ObjCAtCatchStmt : Stmt;
 def ObjCAtCatchStmt : Stmt;

+ 3 - 0
include/clang/Sema/Sema.h

@@ -2530,6 +2530,9 @@ public:
                           SourceLocation RParenLoc,
                           SourceLocation RParenLoc,
                           bool MSAsm = false);
                           bool MSAsm = false);
 
 
+  StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc,
+                            std::string &AsmString,
+                            SourceLocation EndLoc);
 
 
   VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
   VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
                                   SourceLocation StartLoc,
                                   SourceLocation StartLoc,

+ 4 - 0
include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h

@@ -285,6 +285,10 @@ public:
 
 
   /// VisitAsmStmt - Transfer function logic for inline asm.
   /// VisitAsmStmt - Transfer function logic for inline asm.
   void VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst);
   void VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+  /// VisitMSAsmStmt - Transfer function logic for MS inline asm.
+  void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
+                      ExplodedNodeSet &Dst);
   
   
   /// VisitBlockExpr - Transfer function logic for BlockExprs.
   /// VisitBlockExpr - Transfer function logic for BlockExprs.
   void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, 
   void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, 

+ 6 - 0
lib/AST/Stmt.cpp

@@ -550,6 +550,12 @@ AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
   std::copy(clobbers, clobbers + NumClobbers, Clobbers);
   std::copy(clobbers, clobbers + NumClobbers, Clobbers);
 }
 }
 
 
+MSAsmStmt::MSAsmStmt(ASTContext &C, SourceLocation asmloc, std::string &asmstr,
+                     SourceLocation endloc)
+  : Stmt(MSAsmStmtClass), AsmLoc(asmloc), EndLoc(endloc), AsmStr(asmstr),
+    IsSimple(true), IsVolatile(true) {
+}
+
 ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
 ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
                                              Stmt *Body,  SourceLocation FCL,
                                              Stmt *Body,  SourceLocation FCL,
                                              SourceLocation RPL)
                                              SourceLocation RPL)

+ 5 - 0
lib/AST/StmtPrinter.cpp

@@ -429,6 +429,11 @@ void StmtPrinter::VisitAsmStmt(AsmStmt *Node) {
   OS << ");\n";
   OS << ");\n";
 }
 }
 
 
+void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) {
+  // FIXME: Implement MS style inline asm statement printer.
+  Indent() << "asm ()";
+}
+
 void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
 void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
   Indent() << "@try";
   Indent() << "@try";
   if (CompoundStmt *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) {
   if (CompoundStmt *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) {

+ 5 - 0
lib/AST/StmtProfile.cpp

@@ -178,6 +178,11 @@ void StmtProfiler::VisitAsmStmt(const AsmStmt *S) {
     VisitStringLiteral(S->getClobber(I));
     VisitStringLiteral(S->getClobber(I));
 }
 }
 
 
+void StmtProfiler::VisitMSAsmStmt(const MSAsmStmt *S) {
+  // FIXME: Implement MS style inline asm statement profiler.
+  VisitStmt(S);
+}
+
 void StmtProfiler::VisitCXXCatchStmt(const CXXCatchStmt *S) {
 void StmtProfiler::VisitCXXCatchStmt(const CXXCatchStmt *S) {
   VisitStmt(S);
   VisitStmt(S);
   VisitType(S->getCaughtType());
   VisitType(S->getCaughtType());

+ 41 - 0
lib/CodeGen/CGStmt.cpp

@@ -133,6 +133,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
 
 
   case Stmt::SwitchStmtClass:   EmitSwitchStmt(cast<SwitchStmt>(*S));     break;
   case Stmt::SwitchStmtClass:   EmitSwitchStmt(cast<SwitchStmt>(*S));     break;
   case Stmt::AsmStmtClass:      EmitAsmStmt(cast<AsmStmt>(*S));           break;
   case Stmt::AsmStmtClass:      EmitAsmStmt(cast<AsmStmt>(*S));           break;
+  case Stmt::MSAsmStmtClass:    EmitMSAsmStmt(cast<MSAsmStmt>(*S));       break;
 
 
   case Stmt::ObjCAtTryStmtClass:
   case Stmt::ObjCAtTryStmtClass:
     EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S));
     EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S));
@@ -1681,3 +1682,43 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
     EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i]);
     EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i]);
   }
   }
 }
 }
+
+void CodeGenFunction::EmitMSAsmStmt(const MSAsmStmt &S) {
+  // Analyze the asm string to decompose it into its pieces.  We know that Sema
+  // has already done this, so it is guaranteed to be successful.
+
+  // Get all the output and input constraints together.
+
+  std::vector<llvm::Value*> Args;
+  std::vector<llvm::Type *> ArgTypes;
+  std::string Constraints;
+
+  // Keep track of inout constraints.
+  
+  // Append the "input" part of inout constraints last.
+
+  // Clobbers
+
+  // Add machine specific clobbers
+  std::string MachineClobbers = Target.getClobbers();
+  if (!MachineClobbers.empty()) {
+    if (!Constraints.empty())
+      Constraints += ',';
+    Constraints += MachineClobbers;
+  }
+
+  llvm::Type *ResultType = VoidTy;
+
+  llvm::FunctionType *FTy =
+    llvm::FunctionType::get(ResultType, ArgTypes, false);
+
+  llvm::InlineAsm *IA =
+    llvm::InlineAsm::get(FTy, *S.getAsmString(), Constraints, true);
+  llvm::CallInst *Result = Builder.CreateCall(IA, Args);
+  Result->addAttribute(~0, llvm::Attribute::NoUnwind);
+
+  // Slap the source location of the inline asm into a !srcloc metadata on the
+  // call.
+
+  // Extract all of the register value results from the asm.
+}

+ 1 - 0
lib/CodeGen/CodeGenFunction.h

@@ -1970,6 +1970,7 @@ public:
   void EmitCaseStmt(const CaseStmt &S);
   void EmitCaseStmt(const CaseStmt &S);
   void EmitCaseStmtRange(const CaseStmt &S);
   void EmitCaseStmtRange(const CaseStmt &S);
   void EmitAsmStmt(const AsmStmt &S);
   void EmitAsmStmt(const AsmStmt &S);
+  void EmitMSAsmStmt(const MSAsmStmt &S);
 
 
   void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S);
   void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S);
   void EmitObjCAtTryStmt(const ObjCAtTryStmt &S);
   void EmitObjCAtTryStmt(const ObjCAtTryStmt &S);

+ 52 - 33
lib/Parse/ParseStmt.cpp

@@ -20,6 +20,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/PrettyStackTrace.h"
 #include "clang/Basic/PrettyStackTrace.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
 using namespace clang;
 using namespace clang;
 
 
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
@@ -1627,9 +1628,24 @@ StmtResult Parser::ParseReturnStatement() {
 
 
 /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
 /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
 /// this routine is called to collect the tokens for an MS asm statement.
 /// this routine is called to collect the tokens for an MS asm statement.
+///
+/// [MS]  ms-asm-statement:
+///         ms-asm-block
+///         ms-asm-block ms-asm-statement
+///
+/// [MS]  ms-asm-block:
+///         '__asm' ms-asm-line '\n'
+///         '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt]
+///
+/// [MS]  ms-asm-instruction-block
+///         ms-asm-line
+///         ms-asm-line '\n' ms-asm-instruction-block
+///
 StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
 StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
   SourceManager &SrcMgr = PP.getSourceManager();
   SourceManager &SrcMgr = PP.getSourceManager();
   SourceLocation EndLoc = AsmLoc;
   SourceLocation EndLoc = AsmLoc;
+  SmallVector<Token, 4> AsmToks;
+  SmallVector<unsigned, 4> LineEnds;
   do {
   do {
     bool InBraces = false;
     bool InBraces = false;
     unsigned short savedBraceCount = 0;
     unsigned short savedBraceCount = 0;
@@ -1658,9 +1674,6 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
       // If we hit EOF, we're done, period.
       // If we hit EOF, we're done, period.
       if (Tok.is(tok::eof))
       if (Tok.is(tok::eof))
         break;
         break;
-      // When we consume the closing brace, we're done.
-      if (InBraces && BraceCount == savedBraceCount)
-        break;
 
 
       if (!InAsmComment && Tok.is(tok::semi)) {
       if (!InAsmComment && Tok.is(tok::semi)) {
         // A semicolon in an asm is the start of a comment.
         // A semicolon in an asm is the start of a comment.
@@ -1690,8 +1703,15 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
           // does MSVC do here?
           // does MSVC do here?
           break;
           break;
         }
         }
+      } else if (InBraces && Tok.is(tok::r_brace) &&
+                 BraceCount == savedBraceCount + 1) {
+        // Consume the closing brace, and finish
+        EndLoc = ConsumeBrace();
+        break;
       }
       }
 
 
+      AsmToks.push_back(Tok);
+
       // Consume the next token; make sure we don't modify the brace count etc.
       // Consume the next token; make sure we don't modify the brace count etc.
       // if we are in a comment.
       // if we are in a comment.
       EndLoc = TokLoc;
       EndLoc = TokLoc;
@@ -1703,6 +1723,8 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
       ++NumTokensRead;
       ++NumTokensRead;
     } while (1);
     } while (1);
 
 
+    LineEnds.push_back(AsmToks.size());
+
     if (InBraces && BraceCount != savedBraceCount) {
     if (InBraces && BraceCount != savedBraceCount) {
       // __asm without closing brace (this can happen at EOF).
       // __asm without closing brace (this can happen at EOF).
       Diag(Tok, diag::err_expected_rbrace);
       Diag(Tok, diag::err_expected_rbrace);
@@ -1719,24 +1741,33 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
       break;
       break;
     EndLoc = ConsumeToken();
     EndLoc = ConsumeToken();
   } while (1);
   } while (1);
-  // FIXME: Need to actually grab the data and pass it on to Sema.  Ideally,
-  // what Sema wants is a string of the entire inline asm, with one instruction
-  // per line and all the __asm keywords stripped out, and a way of mapping
-  // from any character of that string to its location in the original source
-  // code. I'm not entirely sure how to go about that, though.
-  Token t;
-  t.setKind(tok::string_literal);
-  t.setLiteralData("\"/*FIXME: not done*/\"");
-  t.clearFlag(Token::NeedsCleaning);
-  t.setLength(21);
-  ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
-  ExprVector Constraints(Actions);
-  ExprVector Exprs(Actions);
-  ExprVector Clobbers(Actions);
-  return Actions.ActOnAsmStmt(AsmLoc, true, true, 0, 0, 0,
-                              move_arg(Constraints), move_arg(Exprs),
-                              AsmString.take(), move_arg(Clobbers),
-                              EndLoc, true);
+
+  // Collect the tokens into a string
+  SmallString<512> Asm;
+  SmallString<512> TokenBuf;
+  TokenBuf.resize(512);
+  unsigned AsmLineNum = 0;
+  for (unsigned i = 0, e = AsmToks.size(); i < e; i++) {
+    const char *ThisTokBuf = &TokenBuf[0];
+    bool StringInvalid = false;
+    unsigned ThisTokLen = 
+      Lexer::getSpelling(AsmToks[i], ThisTokBuf, PP.getSourceManager(),
+                         PP.getLangOpts(), &StringInvalid);
+    if (i && (!AsmLineNum || i != LineEnds[AsmLineNum-1]))
+      Asm += ' '; // FIXME: Too much whitespace around punctuation
+    Asm += StringRef(ThisTokBuf, ThisTokLen);
+    if (i + 1 == LineEnds[AsmLineNum] && i + 1 != AsmToks.size()) {
+      Asm += '\n';
+      ++AsmLineNum;
+    }
+  }
+
+  // FIXME: We should be passing the tokens and source locations, rather than
+  // (or possibly in addition to the) AsmString.  Sema is going to interact with
+  // MC to determine Constraints, Clobbers, etc., which would be simplest to
+  // do with the tokens.
+  std::string AsmString = Asm.data();
+  return Actions.ActOnMSAsmStmt(AsmLoc, AsmString, EndLoc);
 }
 }
 
 
 /// ParseAsmStatement - Parse a GNU extended asm statement.
 /// ParseAsmStatement - Parse a GNU extended asm statement.
@@ -1758,18 +1789,6 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
 ///         asm-string-literal
 ///         asm-string-literal
 ///         asm-clobbers ',' asm-string-literal
 ///         asm-clobbers ',' asm-string-literal
 ///
 ///
-/// [MS]  ms-asm-statement:
-///         ms-asm-block
-///         ms-asm-block ms-asm-statement
-///
-/// [MS]  ms-asm-block:
-///         '__asm' ms-asm-line '\n'
-///         '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt]
-///
-/// [MS]  ms-asm-instruction-block
-///         ms-asm-line
-///         ms-asm-line '\n' ms-asm-instruction-block
-///
 StmtResult Parser::ParseAsmStatement(bool &msAsm) {
 StmtResult Parser::ParseAsmStatement(bool &msAsm) {
   assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
   assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
   SourceLocation AsmLoc = ConsumeToken();
   SourceLocation AsmLoc = ConsumeToken();

+ 6 - 0
lib/Sema/AnalysisBasedWarnings.cpp

@@ -189,6 +189,12 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
         continue;
         continue;
       }
       }
     }
     }
+    if (isa<MSAsmStmt>(S)) {
+      // TODO: Verify this is correct.
+      HasFakeEdge = true;
+      HasLiveReturn = true;
+      continue;
+    }
     if (isa<CXXTryStmt>(S)) {
     if (isa<CXXTryStmt>(S)) {
       HasAbnormalEdge = true;
       HasAbnormalEdge = true;
       continue;
       continue;

+ 9 - 0
lib/Sema/SemaStmt.cpp

@@ -2670,6 +2670,15 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
   return Owned(NS);
   return Owned(NS);
 }
 }
 
 
+StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
+                                std::string &AsmString,
+                                SourceLocation EndLoc) {
+  MSAsmStmt *NS =
+    new (Context) MSAsmStmt(Context, AsmLoc, AsmString, EndLoc);
+
+  return Owned(NS);
+}
+
 StmtResult
 StmtResult
 Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
 Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
                            SourceLocation RParen, Decl *Parm,
                            SourceLocation RParen, Decl *Parm,

+ 18 - 0
lib/Sema/TreeTransform.h

@@ -1179,6 +1179,16 @@ public:
                                   RParenLoc, MSAsm);
                                   RParenLoc, MSAsm);
   }
   }
 
 
+  /// \brief Build a new MS style inline asm statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildMSAsmStmt(SourceLocation AsmLoc,
+                              std::string &AsmString,
+                              SourceLocation EndLoc) {
+    return getSema().ActOnMSAsmStmt(AsmLoc, AsmString, EndLoc);
+  }
+
   /// \brief Build a new Objective-C @try statement.
   /// \brief Build a new Objective-C @try statement.
   ///
   ///
   /// By default, performs semantic analysis to build the new statement.
   /// By default, performs semantic analysis to build the new statement.
@@ -5602,6 +5612,14 @@ TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
                                      S->isMSAsm());
                                      S->isMSAsm());
 }
 }
 
 
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) {
+  // No need to transform the asm string literal.
+  return getDerived().RebuildMSAsmStmt(S->getAsmLoc(),
+                                       *S->getAsmString(),
+                                       S->getEndLoc());
+}
 
 
 template<typename Derived>
 template<typename Derived>
 StmtResult
 StmtResult

+ 5 - 0
lib/Serialization/ASTReaderStmt.cpp

@@ -317,6 +317,11 @@ void ASTStmtReader::VisitAsmStmt(AsmStmt *S) {
                                     Clobbers.data(), NumClobbers);
                                     Clobbers.data(), NumClobbers);
 }
 }
 
 
+void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) {
+  // FIXME: Statement reader not yet implemented for MS style inline asm.
+  VisitStmt(S);
+}
+
 void ASTStmtReader::VisitExpr(Expr *E) {
 void ASTStmtReader::VisitExpr(Expr *E) {
   VisitStmt(E);
   VisitStmt(E);
   E->setType(Reader.readType(F, Record, Idx));
   E->setType(Reader.readType(F, Record, Idx));

+ 5 - 0
lib/Serialization/ASTWriterStmt.cpp

@@ -249,6 +249,11 @@ void ASTStmtWriter::VisitAsmStmt(AsmStmt *S) {
   Code = serialization::STMT_ASM;
   Code = serialization::STMT_ASM;
 }
 }
 
 
+void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) {
+  // FIXME: Statement writer not yet implemented for MS style inline asm.
+  VisitStmt(S);
+}
+
 void ASTStmtWriter::VisitExpr(Expr *E) {
 void ASTStmtWriter::VisitExpr(Expr *E) {
   VisitStmt(E);
   VisitStmt(E);
   Writer.AddTypeRef(E->getType(), Record);
   Writer.AddTypeRef(E->getType(), Record);

+ 12 - 0
lib/StaticAnalyzer/Core/ExprEngine.cpp

@@ -670,6 +670,12 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       Bldr.addNodes(Dst);
       Bldr.addNodes(Dst);
       break;
       break;
 
 
+    case Stmt::MSAsmStmtClass:
+      Bldr.takeNodes(Pred);
+      VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
+      break;
+
     case Stmt::BlockExprClass:
     case Stmt::BlockExprClass:
       Bldr.takeNodes(Pred);
       Bldr.takeNodes(Pred);
       VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
       VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
@@ -1813,6 +1819,12 @@ void ExprEngine::VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred,
   Bldr.generateNode(A, Pred, state);
   Bldr.generateNode(A, Pred, state);
 }
 }
 
 
+void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
+                                ExplodedNodeSet &Dst) {
+  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+  Bldr.generateNode(A, Pred, Pred->getState());
+}
+
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 // Visualization.
 // Visualization.
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//

+ 2 - 0
tools/libclang/CIndex.cpp

@@ -3506,6 +3506,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
       return createCXString("ReturnStmt");
       return createCXString("ReturnStmt");
   case CXCursor_AsmStmt:
   case CXCursor_AsmStmt:
       return createCXString("AsmStmt");
       return createCXString("AsmStmt");
+  case CXCursor_MSAsmStmt:
+      return createCXString("MSAsmStmt");
   case CXCursor_ObjCAtTryStmt:
   case CXCursor_ObjCAtTryStmt:
       return createCXString("ObjCAtTryStmt");
       return createCXString("ObjCAtTryStmt");
   case CXCursor_ObjCAtCatchStmt:
   case CXCursor_ObjCAtCatchStmt:

+ 4 - 0
tools/libclang/CXCursor.cpp

@@ -148,6 +148,10 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
   case Stmt::AsmStmtClass:
   case Stmt::AsmStmtClass:
     K = CXCursor_AsmStmt;
     K = CXCursor_AsmStmt;
     break;
     break;
+
+  case Stmt::MSAsmStmtClass:
+    K = CXCursor_MSAsmStmt;
+    break;
   
   
   case Stmt::ObjCAtTryStmtClass:
   case Stmt::ObjCAtTryStmtClass:
     K = CXCursor_ObjCAtTryStmt;
     K = CXCursor_ObjCAtTryStmt;

+ 5 - 0
tools/libclang/RecursiveASTVisitor.h

@@ -1767,6 +1767,11 @@ DEF_TRAVERSE_STMT(AsmStmt, {
     // children() iterates over inputExpr and outputExpr.
     // children() iterates over inputExpr and outputExpr.
   })
   })
 
 
+DEF_TRAVERSE_STMT(MSAsmStmt, {
+    // FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc.  Once
+    // added this needs to be implemented.
+  })
+
 DEF_TRAVERSE_STMT(CXXCatchStmt, {
 DEF_TRAVERSE_STMT(CXXCatchStmt, {
     TRY_TO(TraverseDecl(S->getExceptionDecl()));
     TRY_TO(TraverseDecl(S->getExceptionDecl()));
     // children() iterates over the handler block.
     // children() iterates over the handler block.