diff options
-rw-r--r-- | docs/PCHInternals.html | 30 | ||||
-rw-r--r-- | include/clang/Frontend/ASTConsumers.h | 2 | ||||
-rw-r--r-- | include/clang/Frontend/CompilerInstance.h | 7 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 12 | ||||
-rw-r--r-- | include/clang/Frontend/PCHWriter.h | 3 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/GeneratePCH.cpp | 11 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 3 |
9 files changed, 64 insertions, 11 deletions
diff --git a/docs/PCHInternals.html b/docs/PCHInternals.html index e21ec5e90d..109d5ed025 100644 --- a/docs/PCHInternals.html +++ b/docs/PCHInternals.html @@ -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 diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index e42b1f2cd9..5718979ba1 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -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 diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 06dc8004a6..54ce8bfe3b 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -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. diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 4da96044c5..afa6d93ef2 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -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 }; diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 1e1ce51e4a..0b0c866bd6 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -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); diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 0ff70edf8b..fa5338d30e 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -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); } diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index f0b86a9214..400d35361c 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -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, diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp index 6251bac047..9be103e06e 100644 --- a/lib/Frontend/GeneratePCH.cpp +++ b/lib/Frontend/GeneratePCH.cpp @@ -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); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 8684a06eb0..18ceef99c9 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -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; |