PCH support for inline assembly statements.

This completes support for all of C (+ extensions). We can (again)
build a PCH file for Carbon.h.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69385 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 8889312..da7b422 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -262,6 +262,7 @@
     unsigned VisitBreakStmt(BreakStmt *S);
     unsigned VisitReturnStmt(ReturnStmt *S);
     unsigned VisitDeclStmt(DeclStmt *S);
+    unsigned VisitAsmStmt(AsmStmt *S);
     unsigned VisitExpr(Expr *E);
     unsigned VisitPredefinedExpr(PredefinedExpr *E);
     unsigned VisitDeclRefExpr(DeclRefExpr *E);
@@ -456,6 +457,42 @@
   return 0;
 }
 
+unsigned PCHStmtReader::VisitAsmStmt(AsmStmt *S) {
+  VisitStmt(S);
+  unsigned NumOutputs = Record[Idx++];
+  unsigned NumInputs = Record[Idx++];
+  unsigned NumClobbers = Record[Idx++];
+  S->setAsmLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setVolatile(Record[Idx++]);
+  S->setSimple(Record[Idx++]);
+  
+  unsigned StackIdx 
+    = StmtStack.size() - (NumOutputs*2 + NumInputs*2 + NumClobbers + 1);
+  S->setAsmString(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
+
+  // Outputs and inputs
+  llvm::SmallVector<std::string, 16> Names;
+  llvm::SmallVector<StringLiteral*, 16> Constraints;
+  llvm::SmallVector<Stmt*, 16> Exprs;
+  for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) {
+    Names.push_back(Reader.ReadString(Record, Idx));
+    Constraints.push_back(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
+    Exprs.push_back(StmtStack[StackIdx++]);
+  }
+  S->setOutputsAndInputs(NumOutputs, NumInputs,
+                         &Names[0], &Constraints[0], &Exprs[0]);
+
+  // Constraints
+  llvm::SmallVector<StringLiteral*, 16> Clobbers;
+  for (unsigned I = 0; I != NumClobbers; ++I)
+    Clobbers.push_back(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
+  S->setClobbers(&Clobbers[0], NumClobbers);
+
+  assert(StackIdx == StmtStack.size() && "Error deserializing AsmStmt");
+  return NumOutputs*2 + NumInputs*2 + NumClobbers + 1;
+}
+
 unsigned PCHStmtReader::VisitExpr(Expr *E) {
   VisitStmt(E);
   E->setType(Reader.GetType(Record[Idx++]));
@@ -2273,6 +2310,10 @@
       S = new (Context) DeclStmt(Empty);
       break;
 
+    case pch::STMT_ASM:
+      S = new (Context) AsmStmt(Empty);
+      break;
+
     case pch::EXPR_PREDEFINED:
       S = new (Context) PredefinedExpr(Empty);
       break;
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index e71a600..5775ac4 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -463,6 +463,7 @@
     void VisitBreakStmt(BreakStmt *S);
     void VisitReturnStmt(ReturnStmt *S);
     void VisitDeclStmt(DeclStmt *S);
+    void VisitAsmStmt(AsmStmt *S);
     void VisitExpr(Expr *E);
     void VisitPredefinedExpr(PredefinedExpr *E);
     void VisitDeclRefExpr(DeclRefExpr *E);
@@ -640,6 +641,38 @@
   Code = pch::STMT_DECL;
 }
 
+void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) {
+  VisitStmt(S);
+  Record.push_back(S->getNumOutputs());
+  Record.push_back(S->getNumInputs());
+  Record.push_back(S->getNumClobbers());
+  Writer.AddSourceLocation(S->getAsmLoc(), Record);
+  Writer.AddSourceLocation(S->getRParenLoc(), Record);
+  Record.push_back(S->isVolatile());
+  Record.push_back(S->isSimple());
+  Writer.WriteSubStmt(S->getAsmString());
+
+  // Outputs
+  for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
+    Writer.AddString(S->getOutputName(I), Record);
+    Writer.WriteSubStmt(S->getOutputConstraintLiteral(I));
+    Writer.WriteSubStmt(S->getOutputExpr(I));
+  }
+
+  // Inputs
+  for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) {
+    Writer.AddString(S->getInputName(I), Record);
+    Writer.WriteSubStmt(S->getInputConstraintLiteral(I));
+    Writer.WriteSubStmt(S->getInputExpr(I));
+  }
+
+  // Clobbers
+  for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
+    Writer.WriteSubStmt(S->getClobber(I));
+
+  Code = pch::STMT_ASM;
+}
+
 void PCHStmtWriter::VisitExpr(Expr *E) {
   VisitStmt(E);
   Writer.AddTypeRef(E->getType(), Record);
@@ -1505,9 +1538,7 @@
            Var->getStorageClass() == VarDecl::Static))
         ExternalDefinitions.push_back(ID);
     } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) {
-      if (Func->isThisDeclarationADefinition() &&
-          Func->getStorageClass() != FunctionDecl::Static &&
-          !Func->isInline())
+      if (Func->isThisDeclarationADefinition())
         ExternalDefinitions.push_back(ID);
     }
   }