18bd25b421f728cb7c33a3bcc21a4fc60e835c5e8Chandler Carruth//===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//
32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//                     The LLVM Compiler Infrastructure
42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//
52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// This file is distributed under the University of Illinois Open Source
62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// License. See LICENSE.TXT for details.
72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//
82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//===----------------------------------------------------------------------===//
92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//
108bd25b421f728cb7c33a3bcc21a4fc60e835c5e8Chandler Carruth//  This file defines the PCHGenerator, which as a SemaConsumer that generates
118bd25b421f728cb7c33a3bcc21a4fc60e835c5e8Chandler Carruth//  a PCH file.
122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//
132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//===----------------------------------------------------------------------===//
142cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
157faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl#include "clang/Serialization/ASTWriter.h"
162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "clang/AST/ASTConsumer.h"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ASTContext.h"
184fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor#include "clang/Basic/FileManager.h"
1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h"
2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/SemaConsumer.h"
212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "llvm/Bitcode/BitstreamWriter.h"
222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "llvm/Support/raw_ostream.h"
232cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <string>
242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorusing namespace clang;
262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
271eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpPCHGenerator::PCHGenerator(const Preprocessor &PP,
28467dc88512b4ba4bb16e274ea3771dc1415d31daDouglas Gregor                           StringRef OutputFile,
291a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor                           clang::Module *Module,
30832d620b4ae0fc5fe28561b885b4cfc65cf5c9abDouglas Gregor                           StringRef isysroot,
311f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis                           raw_ostream *OS, bool AllowASTWithErrors)
32a8cc6ce36e70e2afa22ab6b4340035cb3941c2ebDouglas Gregor  : PP(PP), OutputFile(OutputFile), Module(Module),
337143aab97c6e849a5a5005b7853b8c7d5af008edDouglas Gregor    isysroot(isysroot.str()), Out(OS),
346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SemaPtr(nullptr), Stream(Buffer), Writer(Stream),
351f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis    AllowASTWithErrors(AllowASTWithErrors),
361f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis    HasEmittedPCH(false) {
374947e25dd9f7ac1f2176d63262563ba3e96538feDouglas Gregor}
384947e25dd9f7ac1f2176d63262563ba3e96538feDouglas Gregor
394947e25dd9f7ac1f2176d63262563ba3e96538feDouglas GregorPCHGenerator::~PCHGenerator() {
404fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor}
414fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor
422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
431f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis  // Don't create a PCH if there were fatal failures during module loading.
441f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis  if (PP.getModuleLoader().HadFatalFailure)
451f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis    return;
461f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis
471f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis  bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
481f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis  if (hasErrors && !AllowASTWithErrors)
492cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    return;
5089d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor
512cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Emit the PCH file
52e7785040107266d01ebdcc066365f70b7ace371fDouglas Gregor  assert(SemaPtr && "No Sema?");
531f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis  Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, hasErrors);
542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Write the generated bitstream to "Out".
5666d6f048471aad6daf67b3ea804b54fbea72a076Eli Friedman  Out->write((char *)&Buffer.front(), Buffer.size());
572cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Make sure it hits disk now.
5966d6f048471aad6daf67b3ea804b54fbea72a076Eli Friedman  Out->flush();
6030c514c225342844700ed4640ec6d90ddf0e12b2Sebastian Redl
6130c514c225342844700ed4640ec6d90ddf0e12b2Sebastian Redl  // Free up some memory, in case the process is kept alive.
6230c514c225342844700ed4640ec6d90ddf0e12b2Sebastian Redl  Buffer.clear();
631f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis
641f01f7c160c06f8290b4f1c203e36b242074c6b1Argyrios Kyrtzidis  HasEmittedPCH = true;
652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
662cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
677b90340c9c7d07aef4e301e72b5e8a30d5f4f0c8Argyrios KyrtzidisASTMutationListener *PCHGenerator::GetASTMutationListener() {
689293ba8e26fcba18505b273ecc9b66645133fcceDouglas Gregor  return &Writer;
697b90340c9c7d07aef4e301e72b5e8a30d5f4f0c8Argyrios Kyrtzidis}
707b90340c9c7d07aef4e301e72b5e8a30d5f4f0c8Argyrios Kyrtzidis
71571db7f0cb31789737be92fce1c1b738e6dbe795Sebastian RedlASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
72ffaab3e2bb13991bb3357e80f14bcae3745b2347Sebastian Redl  return &Writer;
73ffaab3e2bb13991bb3357e80f14bcae3745b2347Sebastian Redl}
74