Introduce a PCHContainerOperations interface (NFC).

A PCHContainerOperations abstract interface provides operations for
creating and unwrapping containers for serialized ASTs (precompiled
headers and clang modules). The default implementation is
RawPCHContainerOperations, which uses a flat file for the output.

The main application for this interface will be an
ObjectFilePCHContainerOperations implementation that uses LLVM to
wrap the module in an ELF/Mach-O/COFF container to store debug info
alongside the AST.

rdar://problem/20091852

llvm-svn: 240225
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index f3677f8..be30d43 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -80,8 +80,9 @@
                 ASTDeserializationListener *deserialListener = nullptr) {
   Preprocessor &PP = CI.getPreprocessor();
   std::unique_ptr<ASTReader> Reader;
-  Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"",
-                             /*DisableValidation=*/true));
+  Reader.reset(new ASTReader(PP, CI.getASTContext(),
+                             *CI.getPCHContainerOperations(),
+                             /*isysroot=*/"", /*DisableValidation=*/true));
   for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
     StringRef sr(bufNames[ti]);
     Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
@@ -145,7 +146,8 @@
     IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
         new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
 
-    std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+    std::unique_ptr<CompilerInstance> Clang(
+        new CompilerInstance(CI.getPCHContainerOperations()));
     Clang->setInvocation(CInvok.release());
     Clang->setDiagnostics(Diags.get());
     Clang->setTarget(TargetInfo::CreateTargetInfo(
@@ -157,11 +159,9 @@
                                                  &Clang->getPreprocessor());
     Clang->createASTContext();
 
-    SmallVector<char, 256> serialAST;
-    llvm::raw_svector_ostream OS(serialAST);
-    auto consumer =
-        llvm::make_unique<PCHGenerator>(Clang->getPreprocessor(), "-", nullptr,
-                                        /*isysroot=*/"", &OS);
+    auto Buffer = std::make_shared<PCHBuffer>();
+    auto consumer = llvm::make_unique<PCHGenerator>(
+        Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer);
     Clang->getASTContext().setASTMutationListener(
                                             consumer->GetASTMutationListener());
     Clang->setASTConsumer(std::move(consumer));
@@ -198,7 +198,11 @@
 
     ParseAST(Clang->getSema());
     Clang->getDiagnosticClient().EndSourceFile();
-    SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str()));
+    assert(Buffer->IsComplete && "serialization did not complete");
+    auto &serialAST = Buffer->Data;
+    SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
+        StringRef(serialAST.data(), serialAST.size())));
+    serialAST.clear();
     source->CIs.push_back(Clang.release());
   }