]> granicus.if.org Git - clang/commitdiff
Some preparatory work for chained PCH. No functionality change.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Thu, 8 Jul 2010 22:01:51 +0000 (22:01 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Thu, 8 Jul 2010 22:01:51 +0000 (22:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107915 91177308-0d34-0410-b5e6-96231b3b80d8

docs/PCHInternals.html
include/clang/Frontend/ASTConsumers.h
include/clang/Frontend/CompilerInstance.h
include/clang/Frontend/PCHBitCodes.h
include/clang/Frontend/PCHWriter.h
lib/Frontend/CompilerInstance.cpp
lib/Frontend/FrontendActions.cpp
lib/Frontend/GeneratePCH.cpp
lib/Frontend/PCHWriter.cpp

index e21ec5e90df348eb66355723a7a23ffbabc4a72b..109d5ed025580c479623c46ec711e9bf1c476340 100644 (file)
@@ -144,6 +144,15 @@ deserialized from the precompiled header. These statistics can be
 useful to determine whether the precompiled header implementation can
 be improved by making more of the implementation lazy.</p>
 
+<p>Precompiled headers can be chained. When you create a PCH while
+including an existing PCH, Clang can create the new PCH by referencing
+the original file and only writing the new data to the new file. For
+example, you could create a PCH out of all the headers that are very
+commonly used throughout your project, and then create a PCH for every
+single source file in the project that includes the code that is
+specific to that file, so that recompiling the file itself is very fast,
+without duplicating the data from the common headers for every file.</p>
+
 <h2 id="contents">Precompiled Header Contents</h2>
 
 <img src="PCHLayout.png" align="right" alt="Precompiled header layout">
@@ -209,6 +218,27 @@ contents are verified along with the rest of the metadata.</dd>
 
 </dl>
 
+<p>A chained PCH file (that is, one that references another PCH) has
+a slightly different metadata block, which contains the following
+information:</p>
+
+<dl>
+  <dt>Referenced file</dt>
+  <dd>The name of the referenced PCH file. It is looked up like a file
+specified using -include-pch.</dd>
+
+  <dt>PCH version</dt>
+  <dd>This is the same as in normal PCH files.</dd>
+
+  <dt>Original file name</dt>
+  <dd>The full path of the header that was used to generate this
+precompiled header.</dd>
+
+</dl>
+
+<p>The language options, target architecture and predefines buffer data
+is taken from the end of the chain, since they have to match anyway.</p>
+
 <h3 id="sourcemgr">Source Manager Block</h3>
 
 <p>The source manager block contains the serialized representation of
index e42b1f2cd9cd1387c3a080d5303f750506bda2d4..5718979ba1db0ae05481c33fab6a897ed8383f74 100644 (file)
@@ -29,6 +29,7 @@ class CodeGenOptions;
 class Diagnostic;
 class FileManager;
 class LangOptions;
+class PCHReader;
 class Preprocessor;
 class TargetOptions;
 
@@ -62,6 +63,7 @@ ASTConsumer *CreateDeclContextPrinter();
 // times.
 ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
                                 llvm::raw_ostream *OS,
+                                const PCHReader *Chain,
                                 const char *isysroot = 0);
 
 // Inheritance viewer: for C++ code, creates a graph of the inheritance
index 06dc8004a652ee928282e501fa8dfe7be26b066a..54ce8bfe3ba0c572a0c5df39dd974958030c88fd 100644 (file)
@@ -34,6 +34,7 @@ class DiagnosticClient;
 class ExternalASTSource;
 class FileManager;
 class FrontendAction;
+class PCHReader;
 class Preprocessor;
 class SourceManager;
 class TargetInfo;
@@ -96,6 +97,9 @@ class CompilerInstance {
   /// The list of active output files.
   std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
 
+  /// The PCH reader. Not owned; the ASTContext owns this.
+  PCHReader *Reader;
+
   void operator=(const CompilerInstance &);  // DO NOT IMPLEMENT
   CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT
 public:
@@ -507,6 +511,9 @@ public:
   createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot,
                              Preprocessor &PP, ASTContext &Context);
 
+  /// Get the PCH reader, if any.
+  PCHReader *getPCHReader() { return Reader; }
+
   /// Create a code completion consumer using the invocation; note that this
   /// will cause the source manager to truncate the input source file at the
   /// completion point.
index 4da96044c5d1b7e6ac81770bd5f67dc4b2cb4ef3..afa6d93ef2286c8c507a1273a663ed3ae6b05f08 100644 (file)
@@ -30,10 +30,10 @@ namespace clang {
     /// designed for the previous version could not support reading
     /// the new version), this number should be increased.
     ///
-    /// Version 3 of PCH files also requires that the version control branch and
+    /// Version 4 of PCH files also requires that the version control branch and
     /// revision match exactly, since there is no backward compatibility of
     /// PCH files at this time.
-    const unsigned VERSION_MAJOR = 3;
+    const unsigned VERSION_MAJOR = 4;
 
     /// \brief PCH minor version number supported by this version of
     /// Clang.
@@ -47,7 +47,7 @@ namespace clang {
 
     /// \brief An ID number that refers to a declaration in a PCH file.
     ///
-    /// The ID numbers of types are consecutive (in order of
+    /// The ID numbers of declarations are consecutive (in order of
     /// discovery) and start at 2. 0 is reserved for NULL, and 1 is
     /// reserved for the translation unit declaration.
     typedef uint32_t DeclID;
@@ -232,7 +232,11 @@ namespace clang {
       VTABLE_USES = 24,
 
       /// \brief Record code for the array of dynamic classes.
-      DYNAMIC_CLASSES = 25
+      DYNAMIC_CLASSES = 25,
+
+      /// \brief Record code for the chained PCH metadata, including the
+      /// PCH version and the name of the PCH this is chained to.
+      CHAINED_METADATA = 26
 
     };
 
index 1e1ce51e4a0a52900969e45ae1d8f6aa7547875a..0b0c866bd6dfa120e67b372fc5eec01da94a96a0 100644 (file)
@@ -39,6 +39,7 @@ class CXXBaseOrMemberInitializer;
 class LabelStmt;
 class MacroDefinition;
 class MemorizeStatCalls;
+class PCHReader;
 class Preprocessor;
 class Sema;
 class SourceManager;
@@ -257,7 +258,7 @@ public:
   /// \param PPRec Record of the preprocessing actions that occurred while
   /// preprocessing this file, e.g., macro instantiations
   void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
-                const char* isysroot);
+                const PCHReader *Chain, const char* isysroot);
 
   /// \brief Emit a source location.
   void AddSourceLocation(SourceLocation Loc, RecordData &Record);
index 0ff70edf8b4ac9cce89ab96b54753962d7ea9bd3..fa5338d30e6c8be2a40555be82d3e86859fd3c84 100644 (file)
@@ -255,6 +255,8 @@ void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
   llvm::OwningPtr<ExternalASTSource> Source;
   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
                                           getPreprocessor(), getASTContext()));
+  // Remember the PCHReader, but in a non-owning way.
+  Reader = static_cast<PCHReader*>(Source.get());
   getASTContext().setExternalSource(Source);
 }
 
index f0b86a9214af7e209538365d72248a013098dd48..400d35361c9a116b73890ea96227d6ff39bb97d8 100644 (file)
@@ -81,9 +81,10 @@ ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
     return 0;
 
   if (CI.getFrontendOpts().RelocatablePCH)
-    return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());
+    return CreatePCHGenerator(CI.getPreprocessor(), OS,
+                              CI.getPCHReader(), Sysroot.c_str());
 
-  return CreatePCHGenerator(CI.getPreprocessor(), OS);
+  return CreatePCHGenerator(CI.getPreprocessor(), OS, CI.getPCHReader());
 }
 
 ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
index 6251bac04758550f837892f55d7e13a4e847ef14..9be103e06eb0bc13c566ebceeefd091a8555f343 100644 (file)
@@ -28,6 +28,7 @@ using namespace clang;
 namespace {
   class PCHGenerator : public SemaConsumer {
     const Preprocessor &PP;
+    const PCHReader *Chain;
     const char *isysroot;
     llvm::raw_ostream *Out;
     Sema *SemaPtr;
@@ -35,6 +36,7 @@ namespace {
 
   public:
     explicit PCHGenerator(const Preprocessor &PP,
+                          const PCHReader *Chain,
                           const char *isysroot,
                           llvm::raw_ostream *Out);
     virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
@@ -43,9 +45,11 @@ namespace {
 }
 
 PCHGenerator::PCHGenerator(const Preprocessor &PP,
+                           const PCHReader *Chain,
                            const char *isysroot,
                            llvm::raw_ostream *OS)
-  : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0) {
+  : PP(PP), Chain(Chain), isysroot(isysroot), Out(OS), SemaPtr(0),
+    StatCalls(0) {
 
   // Install a stat() listener to keep track of all of the stat()
   // calls.
@@ -64,7 +68,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
 
   // Emit the PCH file
   assert(SemaPtr && "No Sema?");
-  Writer.WritePCH(*SemaPtr, StatCalls, isysroot);
+  Writer.WritePCH(*SemaPtr, StatCalls, Chain, isysroot);
 
   // Write the generated bitstream to "Out".
   Out->write((char *)&Buffer.front(), Buffer.size());
@@ -75,6 +79,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
 
 ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP,
                                        llvm::raw_ostream *OS,
+                                       const PCHReader *Chain,
                                        const char *isysroot) {
-  return new PCHGenerator(PP, isysroot, OS);
+  return new PCHGenerator(PP, Chain, isysroot, OS);
 }
index 8684a06eb0bbede0c21b49f6856eee4313a05f1d..18ceef99c98aefdb0c7ff29e9699d81940324686 100644 (file)
@@ -628,6 +628,7 @@ void PCHWriter::WriteBlockInfoBlock() {
   RECORD(VERSION_CONTROL_BRANCH_REVISION);
   RECORD(UNUSED_STATIC_FUNCS);
   RECORD(MACRO_DEFINITION_OFFSETS);
+  RECORD(CHAINED_METADATA);
   
   // SourceManager Block.
   BLOCK(SOURCE_MANAGER_BLOCK);
@@ -2075,7 +2076,7 @@ PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
     NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) { }
 
 void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
-                         const char *isysroot) {
+                         const PCHReader *Chain, const char *isysroot) {
   using namespace llvm;
 
   ASTContext &Context = SemaRef.Context;