Index: include/clang/Basic/StmtNodes.td
===================================================================
--- include/clang/Basic/StmtNodes.td	(revision 158214)
+++ include/clang/Basic/StmtNodes.td	(working copy)
@@ -31,6 +31,9 @@
 // GNU Extensions
 def AsmStmt : Stmt;
 
+// MS Extensions
+def MSAsmStmt : Stmt;
+
 // Obj-C statements
 def ObjCAtTryStmt : Stmt;
 def ObjCAtCatchStmt : Stmt;
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 158214)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -2528,6 +2528,9 @@
                           SourceLocation RParenLoc,
                           bool MSAsm = false);
 
+  StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc,
+                            Expr *AsmString,
+                            SourceLocation EndLoc);
 
   VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
                                   SourceLocation StartLoc,
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h	(revision 158214)
+++ include/clang/AST/Stmt.h	(working copy)
@@ -1606,6 +1606,104 @@
   }
 };
 
+/// MSAsmStmt - This represents a MS inline-assembly statement extension.
+///
+class MSAsmStmt : public Stmt {
+  SourceLocation AsmLoc, EndLoc;
+  StringLiteral *AsmStr;
+
+  bool IsSimple;
+  bool IsVolatile;
+
+  unsigned NumOutputs;
+  unsigned NumInputs;
+  unsigned NumClobbers;
+
+  // FIXME: If we wanted to, we could allocate all of these in one big array.
+  IdentifierInfo **Names;
+  StringLiteral **Constraints;
+  Stmt **Exprs;
+  StringLiteral **Clobbers;
+
+public:
+  MSAsmStmt(ASTContext &C, SourceLocation asmloc, StringLiteral *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 StringLiteral *getAsmString() const { return AsmStr; }
+  StringLiteral *getAsmString() { return AsmStr; }
+  void setAsmString(StringLiteral *E) { AsmStr = E; }
+
+  //===--- Output operands ---===//
+
+  //===--- Input operands ---===//
+
+  //===--- 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; }
+
+  // Input expr iterators.
+
+  typedef ExprIterator inputs_iterator;
+  typedef ConstExprIterator const_inputs_iterator;
+
+  inputs_iterator begin_inputs() {
+    return &Exprs[0] + NumOutputs;
+  }
+
+  inputs_iterator end_inputs() {
+    return &Exprs[0] + NumOutputs + NumInputs;
+  }
+
+  const_inputs_iterator begin_inputs() const {
+    return &Exprs[0] + NumOutputs;
+  }
+
+  const_inputs_iterator end_inputs() const {
+    return &Exprs[0] + NumOutputs + NumInputs;
+  }
+
+  // Output expr iterators.
+
+  typedef ExprIterator outputs_iterator;
+  typedef ConstExprIterator const_outputs_iterator;
+
+  outputs_iterator begin_outputs() {
+    return &Exprs[0];
+  }
+  outputs_iterator end_outputs() {
+    return &Exprs[0] + NumOutputs;
+  }
+
+  const_outputs_iterator begin_outputs() const {
+    return &Exprs[0];
+  }
+  const_outputs_iterator end_outputs() const {
+    return &Exprs[0] + NumOutputs;
+  }
+
+  child_range children() {
+    return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs);
+  }
+};
+
 class SEHExceptStmt : public Stmt {
   SourceLocation  Loc;
   Stmt           *Children[2];
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h	(revision 158214)
+++ include/clang/AST/RecursiveASTVisitor.h	(working copy)
@@ -1826,6 +1826,11 @@
     // children() iterates over inputExpr and outputExpr.
   })
 
+DEF_TRAVERSE_STMT(MSAsmStmt, { 
+    // FIXME: MS Asm doesn't currently parse Input, Output, Clobbers, etc.  Once
+    // added this needs to be implemented.
+  })
+
 DEF_TRAVERSE_STMT(CXXCatchStmt, {
     TRY_TO(TraverseDecl(S->getExceptionDecl()));
     // children() iterates over the handler block.
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h	(revision 158214)
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h	(working copy)
@@ -285,6 +285,10 @@
 
   /// VisitAsmStmt - Transfer function logic for inline asm.
   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.
   void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, 
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h	(revision 158214)
+++ include/clang-c/Index.h	(working copy)
@@ -1944,57 +1944,61 @@
    */
   CXCursor_AsmStmt                       = 215,
 
+  /** \brief A MS inline assembly statement extension.
+   */
+  CXCursor_MSAsmStmt                     = 216,
+
   /** \brief Objective-C's overall @try-@catch-@finally statement.
    */
-  CXCursor_ObjCAtTryStmt                 = 216,
+  CXCursor_ObjCAtTryStmt                 = 217,
 
   /** \brief Objective-C's @catch statement.
    */
-  CXCursor_ObjCAtCatchStmt               = 217,
+  CXCursor_ObjCAtCatchStmt               = 218,
 
   /** \brief Objective-C's @finally statement.
    */
-  CXCursor_ObjCAtFinallyStmt             = 218,
+  CXCursor_ObjCAtFinallyStmt             = 219,
 
   /** \brief Objective-C's @throw statement.
    */
-  CXCursor_ObjCAtThrowStmt               = 219,
+  CXCursor_ObjCAtThrowStmt               = 220,
 
   /** \brief Objective-C's @synchronized statement.
    */
-  CXCursor_ObjCAtSynchronizedStmt        = 220,
+  CXCursor_ObjCAtSynchronizedStmt        = 221,
 
   /** \brief Objective-C's autorelease pool statement.
    */
-  CXCursor_ObjCAutoreleasePoolStmt       = 221,
+  CXCursor_ObjCAutoreleasePoolStmt       = 222,
 
   /** \brief Objective-C's collection statement.
    */
-  CXCursor_ObjCForCollectionStmt         = 222,
+  CXCursor_ObjCForCollectionStmt         = 223,
 
   /** \brief C++'s catch statement.
    */
-  CXCursor_CXXCatchStmt                  = 223,
+  CXCursor_CXXCatchStmt                  = 224,
 
   /** \brief C++'s try statement.
    */
-  CXCursor_CXXTryStmt                    = 224,
+  CXCursor_CXXTryStmt                    = 225,
 
   /** \brief C++'s for (* : *) statement.
    */
-  CXCursor_CXXForRangeStmt               = 225,
+  CXCursor_CXXForRangeStmt               = 226,
 
   /** \brief Windows Structured Exception Handling's try statement.
    */
-  CXCursor_SEHTryStmt                    = 226,
+  CXCursor_SEHTryStmt                    = 227,
 
   /** \brief Windows Structured Exception Handling's except statement.
    */
-  CXCursor_SEHExceptStmt                 = 227,
+  CXCursor_SEHExceptStmt                 = 228,
 
   /** \brief Windows Structured Exception Handling's finally statement.
    */
-  CXCursor_SEHFinallyStmt                = 228,
+  CXCursor_SEHFinallyStmt                = 229,
 
   /** \brief The null satement ";": C99 6.8.3p3.
    *
Index: tools/libclang/RecursiveASTVisitor.h
===================================================================
--- tools/libclang/RecursiveASTVisitor.h	(revision 158214)
+++ tools/libclang/RecursiveASTVisitor.h	(working copy)
@@ -1767,6 +1767,11 @@
     // children() iterates over inputExpr and outputExpr.
   })
 
+DEF_TRAVERSE_STMT(MSAsmStmt, {
+    // FIXME: MS Asm doesn't currently parse Input, Output, Clobbers, etc.  Once
+    // added this needs to be implemented.
+  })
+
 DEF_TRAVERSE_STMT(CXXCatchStmt, {
     TRY_TO(TraverseDecl(S->getExceptionDecl()));
     // children() iterates over the handler block.
Index: tools/libclang/CXCursor.cpp
===================================================================
--- tools/libclang/CXCursor.cpp	(revision 158214)
+++ tools/libclang/CXCursor.cpp	(working copy)
@@ -148,6 +148,10 @@
   case Stmt::AsmStmtClass:
     K = CXCursor_AsmStmt;
     break;
+
+  case Stmt::MSAsmStmtClass:
+    K = CXCursor_MSAsmStmt;
+    break;
   
   case Stmt::ObjCAtTryStmtClass:
     K = CXCursor_ObjCAtTryStmt;
Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp	(revision 158214)
+++ tools/libclang/CIndex.cpp	(working copy)
@@ -3505,6 +3505,8 @@
       return createCXString("ReturnStmt");
   case CXCursor_AsmStmt:
       return createCXString("AsmStmt");
+  case CXCursor_MSAsmStmt:
+      return createCXString("MSAsmStmt");
   case CXCursor_ObjCAtTryStmt:
       return createCXString("ObjCAtTryStmt");
   case CXCursor_ObjCAtCatchStmt:
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h	(revision 158214)
+++ lib/Sema/TreeTransform.h	(working copy)
@@ -1179,6 +1179,16 @@
                                   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,
+                              Expr *AsmString,
+                              SourceLocation EndLoc) {
+    return getSema().ActOnMSAsmStmt(AsmLoc, AsmString, EndLoc);
+  }
+
   /// \brief Build a new Objective-C @try statement.
   ///
   /// By default, performs semantic analysis to build the new statement.
@@ -5602,7 +5612,17 @@
                                      S->isMSAsm());
 }
 
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) {
+  // No need to transform the asm string literal.
+  ExprResult AsmString = SemaRef.Owned(S->getAsmString());
 
+  return getDerived().RebuildMSAsmStmt(S->getAsmLoc(),
+                                       AsmString.get(),
+                                       S->getEndLoc());
+}
+
 template<typename Derived>
 StmtResult
 TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp	(revision 158214)
+++ lib/Sema/SemaStmt.cpp	(working copy)
@@ -2671,6 +2671,16 @@
   return Owned(NS);
 }
 
+StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
+                                Expr *asmString,
+                                SourceLocation EndLoc) {
+  StringLiteral *AsmString = cast<StringLiteral>(asmString);
+  MSAsmStmt *NS =
+    new (Context) MSAsmStmt(Context, AsmLoc, AsmString, EndLoc);
+
+  return Owned(NS);
+}
+
 StmtResult
 Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
                            SourceLocation RParen, Decl *Parm,
Index: lib/Sema/AnalysisBasedWarnings.cpp
===================================================================
--- lib/Sema/AnalysisBasedWarnings.cpp	(revision 158214)
+++ lib/Sema/AnalysisBasedWarnings.cpp	(working copy)
@@ -189,6 +189,12 @@
         continue;
       }
     }
+    if (isa<MSAsmStmt>(S)) {
+      // TODO: Verify this is correct.
+      HasFakeEdge = true;
+      HasLiveReturn = true;
+      continue;
+    }
     if (isa<CXXTryStmt>(S)) {
       HasAbnormalEdge = true;
       continue;
Index: lib/AST/Stmt.cpp
===================================================================
--- lib/AST/Stmt.cpp	(revision 158214)
+++ lib/AST/Stmt.cpp	(working copy)
@@ -550,6 +550,12 @@
   std::copy(clobbers, clobbers + NumClobbers, Clobbers);
 }
 
+MSAsmStmt::MSAsmStmt(ASTContext &C, SourceLocation asmloc, StringLiteral *asmstr,
+                     SourceLocation endloc)
+  : Stmt(MSAsmStmtClass), AsmLoc(asmloc), EndLoc(endloc), AsmStr(asmstr),
+    IsSimple(true), IsVolatile(true) {
+}
+
 ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
                                              Stmt *Body,  SourceLocation FCL,
                                              SourceLocation RPL)
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp	(revision 158214)
+++ lib/AST/StmtPrinter.cpp	(working copy)
@@ -429,6 +429,12 @@
   OS << ");\n";
 }
 
+void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) {
+  // FIXME: MS style inline asm still a WIP.
+  Indent() << "asm ";
+  OS << "()";
+}
+
 void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
   Indent() << "@try";
   if (CompoundStmt *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) {
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp	(revision 158214)
+++ lib/AST/StmtProfile.cpp	(working copy)
@@ -178,6 +178,11 @@
     VisitStringLiteral(S->getClobber(I));
 }
 
+void StmtProfiler::VisitMSAsmStmt(const MSAsmStmt *S) {
+  // FIXME: MS style inline asm still a WIP.
+  VisitStmt(S);
+}
+
 void StmtProfiler::VisitCXXCatchStmt(const CXXCatchStmt *S) {
   VisitStmt(S);
   VisitType(S->getCaughtType());
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp	(revision 158214)
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp	(working copy)
@@ -670,6 +670,12 @@
       Bldr.addNodes(Dst);
       break;
 
+    case Stmt::MSAsmStmtClass:
+      Bldr.takeNodes(Pred);
+      VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
+      break;
+
     case Stmt::BlockExprClass:
       Bldr.takeNodes(Pred);
       VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
@@ -1813,6 +1819,30 @@
   Bldr.generateNode(A, Pred, state);
 }
 
+void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
+                                ExplodedNodeSet &Dst) {
+  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+  // We have processed both the inputs and the outputs.  All of the outputs
+  // should evaluate to Locs.  Nuke all of their values.
+
+  // FIXME: Some day in the future it would be nice to allow a "plug-in"
+  // which interprets the inline asm and stores proper results in the
+  // outputs.
+
+  ProgramStateRef state = Pred->getState();
+
+  for (MSAsmStmt::const_outputs_iterator OI = A->begin_outputs(),
+       OE = A->end_outputs(); OI != OE; ++OI) {
+    SVal X = state->getSVal(*OI, Pred->getLocationContext());
+    assert (!isa<NonLoc>(X));  // Should be an Lval, or unknown, undef.
+
+    if (isa<Loc>(X))
+      state = state->bindLoc(cast<Loc>(X), UnknownVal());
+  }
+
+  Bldr.generateNode(A, Pred, state);
+}
+
 //===----------------------------------------------------------------------===//
 // Visualization.
 //===----------------------------------------------------------------------===//
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp	(revision 158214)
+++ lib/CodeGen/CGStmt.cpp	(working copy)
@@ -133,6 +133,7 @@
 
   case Stmt::SwitchStmtClass:   EmitSwitchStmt(cast<SwitchStmt>(*S));     break;
   case Stmt::AsmStmtClass:      EmitAsmStmt(cast<AsmStmt>(*S));           break;
+  case Stmt::MSAsmStmtClass:    EmitMSAsmStmt(cast<MSAsmStmt>(*S));       break;
 
   case Stmt::ObjCAtTryStmtClass:
     EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S));
@@ -1681,3 +1682,46 @@
     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.
+
+  // Assemble the pieces into the final asm string.
+  std::string AsmString = S.getAsmString()->getString().str();
+
+  // 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, AsmString, 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.
+}
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h	(revision 158214)
+++ lib/CodeGen/CodeGenFunction.h	(working copy)
@@ -1970,6 +1970,7 @@
   void EmitCaseStmt(const CaseStmt &S);
   void EmitCaseStmtRange(const CaseStmt &S);
   void EmitAsmStmt(const AsmStmt &S);
+  void EmitMSAsmStmt(const MSAsmStmt &S);
 
   void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S);
   void EmitObjCAtTryStmt(const ObjCAtTryStmt &S);
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp	(revision 158214)
+++ lib/Parse/ParseStmt.cpp	(working copy)
@@ -20,6 +20,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/PrettyStackTrace.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -1630,6 +1631,8 @@
 StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
   SourceManager &SrcMgr = PP.getSourceManager();
   SourceLocation EndLoc = AsmLoc;
+  SmallVector<Token, 4> AsmToks;
+  SmallVector<unsigned, 4> LineEnds;
   do {
     bool InBraces = false;
     unsigned short savedBraceCount = 0;
@@ -1658,9 +1661,6 @@
       // If we hit EOF, we're done, period.
       if (Tok.is(tok::eof))
         break;
-      // When we consume the closing brace, we're done.
-      if (InBraces && BraceCount == savedBraceCount)
-        break;
 
       if (!InAsmComment && Tok.is(tok::semi)) {
         // A semicolon in an asm is the start of a comment.
@@ -1690,8 +1690,15 @@
           // does MSVC do here?
           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.
       // if we are in a comment.
       EndLoc = TokLoc;
@@ -1703,6 +1710,8 @@
       ++NumTokensRead;
     } while (1);
 
+    LineEnds.push_back(AsmToks.size());
+
     if (InBraces && BraceCount != savedBraceCount) {
       // __asm without closing brace (this can happen at EOF).
       Diag(Tok, diag::err_expected_rbrace);
@@ -1719,24 +1728,41 @@
       break;
     EndLoc = ConsumeToken();
   } 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.
+
+  // Collect the tokens into a string
+  SmallString<512> Asm;
+  SmallString<512> TokenBuf;
+  TokenBuf.resize(512);
+  Asm += '"';
+  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;
+    }
+  }
+  Asm += '"';
+
   Token t;
   t.setKind(tok::string_literal);
-  t.setLiteralData("\"/*FIXME: not done*/\"");
+  t.setLiteralData(Asm.data());
   t.clearFlag(Token::NeedsCleaning);
-  t.setLength(21);
+  t.setLength(Asm.size());
   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);
+
+  // FIXME: We should be passing the tokens and source locations, rather than
+  // (or possibly in addition to the) AsmString StringLiteral.  Sema is going
+  // to interact with MC to determine Inputs, Output, Clobbers, etc., which
+  // would be simplest to do with the tokens.
+  return Actions.ActOnMSAsmStmt(AsmLoc, AsmString.take(), EndLoc);
 }
 
 /// ParseAsmStatement - Parse a GNU extended asm statement.
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp	(revision 158214)
+++ lib/Serialization/ASTReaderStmt.cpp	(working copy)
@@ -317,6 +317,11 @@
                                     Clobbers.data(), NumClobbers);
 }
 
+void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) {
+  // FIXME: MS style inline asm still a WIP.
+  VisitStmt(S);
+}
+
 void ASTStmtReader::VisitExpr(Expr *E) {
   VisitStmt(E);
   E->setType(Reader.readType(F, Record, Idx));
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp	(revision 158214)
+++ lib/Serialization/ASTWriterStmt.cpp	(working copy)
@@ -249,6 +249,11 @@
   Code = serialization::STMT_ASM;
 }
 
+void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) {
+  // FIXME: MS style inline asm still a WIP.
+  VisitStmt(S);
+}
+
 void ASTStmtWriter::VisitExpr(Expr *E) {
   VisitStmt(E);
   Writer.AddTypeRef(E->getType(), Record);
