aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-04-09 22:27:44 +0000
committerDouglas Gregor <dgregor@apple.com>2009-04-09 22:27:44 +0000
commit2cf2634ffdb4f7c8d46cef3f8e60a55993f1c57a (patch)
treec9a3838dd8bb8eda8c958dfd28ef7f74c61a66f2
parent8d7f5481a0eeb4c0508202a4bd2b754cfa93c4fe (diff)
Implementation of pre-compiled headers (PCH) based on lazy
de-serialization of abstract syntax trees. PCH support serializes the contents of the abstract syntax tree (AST) to a bitstream. When the PCH file is read, declarations are serialized as-needed. For example, a declaration of a variable "x" will be deserialized only when its VarDecl can be found by a client, e.g., based on name lookup for "x" or traversing the entire contents of the owner of "x". This commit provides the framework for serialization and (lazy) deserialization, along with support for variable and typedef declarations (along with several kinds of types). More declarations/types, along with important auxiliary structures (source manager, preprocessor, etc.), will follow. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68732 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTContext.h14
-rw-r--r--include/clang/AST/DeclBase.h43
-rw-r--r--include/clang/AST/DeclContextInternals.h170
-rw-r--r--include/clang/AST/ExternalASTSource.h94
-rw-r--r--include/clang/Frontend/PCHBitCodes.h239
-rw-r--r--include/clang/Frontend/PCHReader.h169
-rw-r--r--include/clang/Frontend/PCHWriter.h114
-rw-r--r--lib/AST/ASTContext.cpp18
-rw-r--r--lib/AST/DeclBase.cpp112
-rw-r--r--lib/Frontend/PCHReader.cpp602
-rw-r--r--lib/Frontend/PCHWriter.cpp636
-rw-r--r--lib/Sema/SemaDecl.cpp6
-rw-r--r--lib/Sema/SemaLookup.cpp11
-rw-r--r--test/PCH/variables.c6
-rw-r--r--test/PCH/variables.h5
-rwxr-xr-xtest/TestRunner.sh3
-rw-r--r--tools/clang-cc/ASTConsumers.h5
-rw-r--r--tools/clang-cc/GeneratePCH.cpp78
-rw-r--r--tools/clang-cc/clang-cc.cpp23
19 files changed, 2300 insertions, 48 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 873806ffd2..ee9f99c57e 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -24,6 +24,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include "llvm/Support/Allocator.h"
#include <vector>
@@ -36,6 +37,7 @@ namespace clang {
class FileManager;
class ASTRecordLayout;
class Expr;
+ class ExternalASTSource;
class IdentifierTable;
class SelectorTable;
class SourceManager;
@@ -146,6 +148,7 @@ public:
IdentifierTable &Idents;
SelectorTable &Selectors;
DeclarationNameTable DeclarationNames;
+ llvm::OwningPtr<ExternalASTSource> ExternalSource;
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
@@ -190,6 +193,17 @@ public:
~ASTContext();
+ /// \brief Attach an external AST source to the AST context.
+ ///
+ /// The external AST source provides the ability to load parts of
+ /// the abstract syntax tree as needed from some external storage,
+ /// e.g., a precompiled header.
+ void setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source);
+
+ /// \brief Retrieve a pointer to the external AST source associated
+ /// with this AST context, if any.
+ ExternalASTSource *getExternalSource() const { return ExternalSource.get(); }
+
void PrintStats() const;
const std::vector<Type*>& getTypes() const { return Types; }
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 3244c63146..46af4ec6b6 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -349,24 +349,36 @@ class DeclContext {
/// DeclKind - This indicates which class this is.
Decl::Kind DeclKind : 8;
+ /// \brief Whether this declaration context also has some external
+ /// storage that contains additional declarations that are lexically
+ /// part of this context.
+ mutable bool ExternalLexicalStorage : 1;
+
+ /// \brief Whether this declaration context also has some external
+ /// storage that contains additional declarations that are visible
+ /// in this context.
+ mutable bool ExternalVisibleStorage : 1;
+
/// \brief Pointer to the data structure used to lookup declarations
/// within this context, which is a DenseMap<DeclarationName,
/// StoredDeclsList>.
- void* LookupPtr;
+ mutable void* LookupPtr;
/// FirstDecl - The first declaration stored within this declaration
/// context.
- Decl *FirstDecl;
+ mutable Decl *FirstDecl;
/// LastDecl - The last declaration stored within this declaration
/// context. FIXME: We could probably cache this value somewhere
/// outside of the DeclContext, to reduce the size of DeclContext by
/// another pointer.
- Decl *LastDecl;
+ mutable Decl *LastDecl;
protected:
DeclContext(Decl::Kind K)
- : DeclKind(K), LookupPtr(0), FirstDecl(0), LastDecl(0) { }
+ : DeclKind(K), ExternalLexicalStorage(false),
+ ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
+ LastDecl(0) { }
void DestroyDecls(ASTContext &C);
@@ -751,6 +763,26 @@ public:
/// \brief Retrieve the internal representation of the lookup structure.
void* getLookupPtr() const { return LookupPtr; }
+ /// \brief Whether this DeclContext has external storage containing
+ /// additional declarations that are lexically in this context.
+ bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; }
+
+ /// \brief State whether this DeclContext has external storage for
+ /// declarations lexically in this context.
+ void setHasExternalLexicalStorage(bool ES = true) {
+ ExternalLexicalStorage = ES;
+ }
+
+ /// \brief Whether this DeclContext has external storage containing
+ /// additional declarations that are visible in this context.
+ bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; }
+
+ /// \brief State whether this DeclContext has external storage for
+ /// declarations visible in this context.
+ void setHasExternalVisibleStorage(bool ES = true) {
+ ExternalVisibleStorage = ES;
+ }
+
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
#define DECL_CONTEXT(Name) \
@@ -758,6 +790,9 @@ public:
#include "clang/AST/DeclNodes.def"
private:
+ void LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const;
+ void LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const;
+
void buildLookup(ASTContext &Context, DeclContext *DCtx);
void makeDeclVisibleInContextImpl(ASTContext &Context, NamedDecl *D);
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 9341a7de37..7489413be8 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -19,54 +19,128 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
-#include <functional>
+#include <algorithm>
namespace clang {
/// StoredDeclsList - This is an array of decls optimized a common case of only
/// containing one entry.
struct StoredDeclsList {
+ /// The kind of data encoded in this list.
+ enum DataKind {
+ /// \brief The data is a NamedDecl*.
+ DK_Decl = 0,
+ /// \brief The data is a declaration ID (an unsigned value),
+ /// shifted left by 2 bits.
+ DK_DeclID = 1,
+ /// \brief The data is a pointer to a vector (of type VectorTy)
+ /// that contains declarations.
+ DK_Decl_Vector = 2,
+ /// \brief The data is a pointer to a vector (of type VectorTy)
+ /// that contains declaration ID.
+ DK_ID_Vector = 3
+ };
+
/// VectorTy - When in vector form, this is what the Data pointer points to.
- typedef llvm::SmallVector<NamedDecl*, 4> VectorTy;
+ typedef llvm::SmallVector<uintptr_t, 4> VectorTy;
+
+ /// \brief The stored data, which will be either a declaration ID, a
+ /// pointer to a NamedDecl, or a pointer to a vector.
+ uintptr_t Data;
- /// Data - Union of NamedDecl*/VectorTy*.
- llvm::PointerUnion<NamedDecl*, VectorTy*> Data;
public:
- StoredDeclsList() {}
+ StoredDeclsList() : Data(0) {}
+
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
- if (isVector())
- Data = new VectorTy(*Data.get<VectorTy*>());
+ if (VectorTy *RHSVec = RHS.getAsVector()) {
+ VectorTy *New = new VectorTy(*RHSVec);
+ Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
+ }
}
~StoredDeclsList() {
// If this is a vector-form, free the vector.
- if (isVector())
- delete Data.get<VectorTy*>();
+ if (VectorTy *Vector = getAsVector())
+ delete Vector;
}
StoredDeclsList &operator=(const StoredDeclsList &RHS) {
- if (isVector())
- delete Data.get<VectorTy*>();
+ if (VectorTy *Vector = getAsVector())
+ delete Vector;
Data = RHS.Data;
- if (isVector())
- Data = new VectorTy(*Data.get<VectorTy*>());
+ if (VectorTy *RHSVec = RHS.getAsVector()) {
+ VectorTy *New = new VectorTy(*RHSVec);
+ Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
+ }
return *this;
}
- bool isVector() const { return Data.is<VectorTy*>(); }
- bool isInline() const { return Data.is<NamedDecl*>(); }
- bool isNull() const { return Data.isNull(); }
+ bool isNull() const { return (Data & ~0x03) == 0; }
+ NamedDecl *getAsDecl() const {
+ if ((Data & 0x03) != DK_Decl)
+ return 0;
+
+ return reinterpret_cast<NamedDecl *>(Data & ~0x03);
+ }
+
+ VectorTy *getAsVector() const {
+ if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector)
+ return 0;
+
+ return reinterpret_cast<VectorTy *>(Data & ~0x03);
+ }
+
void setOnlyValue(NamedDecl *ND) {
- assert(isInline() && "Not inline");
- Data = ND;
+ assert(!getAsVector() && "Not inline");
+ Data = reinterpret_cast<uintptr_t>(ND);
+ }
+
+ void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) {
+ if (Vec.size() > 1) {
+ VectorTy *Vector = getAsVector();
+ if (!Vector) {
+ Vector = new VectorTy;
+ Data = reinterpret_cast<uintptr_t>(Vector) | DK_Decl_Vector;
+ }
+
+ Vector->resize(Vec.size());
+ std::copy(Vec.begin(), Vec.end(), Vector->begin());
+ return;
+ }
+
+ if (VectorTy *Vector = getAsVector())
+ delete Vector;
+
+ if (Vec.size() == 0)
+ Data = 0;
+ else
+ Data = (Vec[0] << 2) | DK_DeclID;
+ }
+
+ /// \brief Force the stored declarations list to contain actual
+ /// declarations.
+ ///
+ /// This routine will resolve any declaration IDs for declarations
+ /// that may not yet have been loaded from external storage.
+ void materializeDecls(ASTContext &Context);
+
+ bool hasDeclarationIDs() const {
+ DataKind DK = (DataKind)(Data & 0x03);
+ return DK == DK_DeclID || DK == DK_ID_Vector;
}
/// getLookupResult - Return an array of all the decls that this list
/// represents.
DeclContext::lookup_result getLookupResult(ASTContext &Context) {
- // If we have a single inline unit, return it.
- if (isInline()) {
+ if (isNull())
+ return DeclContext::lookup_result(0, 0);
+
+ if (hasDeclarationIDs())
+ materializeDecls(Context);
+
+ // If we have a single NamedDecl, return it.
+ if (getAsDecl()) {
assert(!isNull() && "Empty list isn't allowed");
// Data is a raw pointer to a NamedDecl*, return it.
@@ -74,57 +148,67 @@ public:
return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
}
+ assert(getAsVector() && "Must have a vector at this point");
+ VectorTy &Vector = *getAsVector();
+
// Otherwise, we have a range result.
- VectorTy &V = *Data.get<VectorTy*>();
- return DeclContext::lookup_result(&V[0], &V[0]+V.size());
+ return DeclContext::lookup_result((NamedDecl **)&Vector[0],
+ (NamedDecl **)&Vector[0]+Vector.size());
}
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false.
bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) {
+ if (hasDeclarationIDs())
+ materializeDecls(Context);
+
// Most decls only have one entry in their list, special case it.
- if (isInline()) {
- if (!D->declarationReplaces(Data.get<NamedDecl*>()))
+ if (NamedDecl *OldD = getAsDecl()) {
+ if (!D->declarationReplaces(OldD))
return false;
setOnlyValue(D);
return true;
}
// Determine if this declaration is actually a redeclaration.
- VectorTy &Vec = *Data.get<VectorTy*>();
- VectorTy::iterator RDI
- = std::find_if(Vec.begin(), Vec.end(),
- std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
- D));
- if (RDI == Vec.end())
- return false;
- *RDI = D;
- return true;
+ VectorTy &Vec = *getAsVector();
+ for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
+ OD != ODEnd; ++OD) {
+ NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD);
+ if (D->declarationReplaces(OldD)) {
+ *OD = reinterpret_cast<uintptr_t>(D);
+ return true;
+ }
+ }
+
+ return false;
}
/// AddSubsequentDecl - This is called on the second and later decl when it is
/// not a redeclaration to merge it into the appropriate place in our list.
///
void AddSubsequentDecl(NamedDecl *D) {
+ assert(!hasDeclarationIDs() && "Must materialize before adding decls");
+
// If this is the second decl added to the list, convert this to vector
// form.
- if (isInline()) {
- NamedDecl *OldD = Data.get<NamedDecl*>();
+ if (NamedDecl *OldD = getAsDecl()) {
VectorTy *VT = new VectorTy();
- VT->push_back(OldD);
- Data = VT;
+ VT->push_back(reinterpret_cast<uintptr_t>(OldD));
+ Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector;
}
- VectorTy &Vec = *Data.get<VectorTy*>();
+ VectorTy &Vec = *getAsVector();
if (isa<UsingDirectiveDecl>(D) ||
D->getIdentifierNamespace() == Decl::IDNS_Tag)
- Vec.push_back(D);
- else if (Vec.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
- NamedDecl *TagD = Vec.back();
- Vec.back() = D;
+ Vec.push_back(reinterpret_cast<uintptr_t>(D));
+ else if (reinterpret_cast<NamedDecl *>(Vec.back())
+ ->getIdentifierNamespace() == Decl::IDNS_Tag) {
+ uintptr_t TagD = Vec.back();
+ Vec.back() = reinterpret_cast<uintptr_t>(D);
Vec.push_back(TagD);
} else
- Vec.push_back(D);
+ Vec.push_back(reinterpret_cast<uintptr_t>(D));
}
};
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
new file mode 100644
index 0000000000..17fa72612f
--- /dev/null
+++ b/include/clang/AST/ExternalASTSource.h
@@ -0,0 +1,94 @@
+//===--- ExternalASTSource.h - Abstract External AST Interface --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalASTSource interface,
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class Decl;
+class DeclContext;
+
+/// \brief The deserialized representation of a set of declarations
+/// with the same name that are visible in a given context.
+struct VisibleDeclaration {
+ /// \brief The name of the declarations.
+ DeclarationName Name;
+
+ /// \brief The ID numbers of all of the declarations with this name.
+ ///
+ /// These declarations have not necessarily been de-serialized.
+ llvm::SmallVector<unsigned, 4> Declarations;
+};
+
+/// \brief Abstract interface for external sources of AST nodes.
+///
+/// External AST sources provide AST nodes constructed from some
+/// external source, such as a precompiled header. External AST
+/// sources can resolve types and declarations from abstract IDs into
+/// actual type and declaration nodes, and read parts of declaration
+/// contexts.
+class ExternalASTSource {
+public:
+ virtual ~ExternalASTSource();
+
+ /// \brief Resolve a type ID into a type, potentially building a new
+ /// type.
+ virtual QualType GetType(unsigned ID) = 0;
+
+ /// \brief Resolve a declaration ID into a declaration, potentially
+ /// building a new declaration.
+ virtual Decl *GetDecl(unsigned ID) = 0;
+
+ /// \brief Read all of the declarations lexically stored in a
+ /// declaration context.
+ ///
+ /// \param DC The declaration context whose declarations will be
+ /// read.
+ ///
+ /// \param Decls Vector that will contain the declarations loaded
+ /// from the external source. The caller is responsible for merging
+ /// these declarations with any declarations already stored in the
+ /// declaration context.
+ ///
+ /// \returns true if there was an error while reading the
+ /// declarations for this declaration context.
+ virtual bool ReadDeclsLexicallyInContext(DeclContext *DC,
+ llvm::SmallVectorImpl<unsigned> &Decls) = 0;
+
+ /// \brief Read all of the declarations visible from a declaration
+ /// context.
+ ///
+ /// \param DC The declaration context whose visible declarations
+ /// will be read.
+ ///
+ /// \param Decls A vector of visible declaration structures,
+ /// providing the mapping from each name visible in the declaration
+ /// context to the declaration IDs of declarations with that name.
+ ///
+ /// \returns true if there was an error while reading the
+ /// declarations for this declaration context.
+ virtual bool ReadDeclsVisibleInContext(DeclContext *DC,
+ llvm::SmallVectorImpl<VisibleDeclaration> & Decls) = 0;
+
+ /// \brief Print any statistics that have been gathered regarding
+ /// the external AST source.
+ virtual void PrintStats();
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
new file mode 100644
index 0000000000..8835098361
--- /dev/null
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -0,0 +1,239 @@
+//===- PCHBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines Bitcode enum values for Clang precompiled header files.
+//
+// The enum values defined in this file should be considered permanent. If
+// new features are added, they should have values added at the end of the
+// respective lists.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H
+#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
+
+#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+ namespace pch {
+ const int IDBits = 32;
+ typedef uint32_t ID;
+
+ /// \brief Describes the various kinds of blocks that occur within
+ /// a PCH file.
+ enum BlockIDs {
+ /// \brief The PCH block, which acts as a container around the
+ /// full PCH block.
+ PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+
+ /// \brief The block containing the definitions of all of the
+ /// types used within the PCH file.
+ TYPES_BLOCK_ID,
+
+ /// \brief The block containing the offsets of all of the types
+ /// used within the PCH.
+ ///
+ /// The offsets in this block point into the block identified by
+ /// TYPES_BLOCK_ID, and are indexed by the type ID.
+ TYPE_OFFSETS_BLOCK_ID,
+
+ /// \brief The block containing the definitions of all of the
+ /// declarations stored in the PCH file.
+ DECLS_BLOCK_ID,
+
+ /// \brief The block containing the offsets of all of the
+ /// declarations stored within the PCH file.
+ ///
+ /// The offsets in this block point into the block identified by
+ /// DECLS_BLOCK_ID, and are indexed by the decaration ID.
+ DECL_OFFSETS_BLOCK_ID
+ };
+
+ /// \brief Predefined type IDs.
+ ///
+ /// These type IDs correspond to predefined types in the AST
+ /// context, such as built-in types (int) and special place-holder
+ /// types (the <overload> and <dependent> type markers). Such
+ /// types are never actually serialized, since they will be built
+ /// by the AST context when it is created.
+ enum PredefinedTypeIDs {
+ /// \brief The NULL type.
+ PREDEF_TYPE_NULL_ID = 0,
+ /// \brief The void type.
+ PREDEF_TYPE_VOID_ID = 1,
+ /// \brief The 'bool' or '_Bool' type.
+ PREDEF_TYPE_BOOL_ID = 2,
+ /// \brief The 'char' type, when it is unsigned.
+ PREDEF_TYPE_CHAR_U_ID = 3,
+ /// \brief The 'unsigned char' type.
+ PREDEF_TYPE_UCHAR_ID = 4,
+ /// \brief The 'unsigned short' type.
+ PREDEF_TYPE_USHORT_ID = 5,
+ /// \brief The 'unsigned int' type.
+ PREDEF_TYPE_UINT_ID = 6,
+ /// \brief The 'unsigned long' type.
+ PREDEF_TYPE_ULONG_ID = 7,
+ /// \brief The 'unsigned long long' type.
+ PREDEF_TYPE_ULONGLONG_ID = 8,
+ /// \brief The 'char' type, when it is signed.
+ PREDEF_TYPE_CHAR_S_ID = 9,
+ /// \brief The 'signed char' type.
+ PREDEF_TYPE_SCHAR_ID = 10,
+ /// \brief The C++ 'wchar_t' type.
+ PREDEF_TYPE_WCHAR_ID = 11,
+ /// \brief The (signed) 'short' type.
+ PREDEF_TYPE_SHORT_ID = 12,
+ /// \brief The (signed) 'int' type.
+ PREDEF_TYPE_INT_ID = 13,
+ /// \brief The (signed) 'long' type.
+ PREDEF_TYPE_LONG_ID = 14,
+ /// \brief The (signed) 'long long' type.
+ PREDEF_TYPE_LONGLONG_ID = 15,
+ /// \brief The 'float' type.
+ PREDEF_TYPE_FLOAT_ID = 16,
+ /// \brief The 'double' type.
+ PREDEF_TYPE_DOUBLE_ID = 17,
+ /// \brief The 'long double' type.
+ PREDEF_TYPE_LONGDOUBLE_ID = 18,
+ /// \brief The placeholder type for overloaded function sets.
+ PREDEF_TYPE_OVERLOAD_ID = 19,
+ /// \brief The placeholder type for dependent types.
+ PREDEF_TYPE_DEPENDENT_ID = 20
+ };
+
+ /// \brief The number of predefined type IDs that are reserved for
+ /// the PREDEF_TYPE_* constants.
+ ///
+ /// Type IDs for non-predefined types will start at
+ /// NUM_PREDEF_TYPE_IDs.
+ const unsigned NUM_PREDEF_TYPE_IDS = 100;
+
+ /// \brief Record codes for each kind of type.
+ ///
+ /// These constants describe the records that can occur within a
+ /// block identified by TYPES_BLOCK_ID in the PCH file. Each
+ /// constant describes a record for a specific type class in the
+ /// AST.
+ enum TypeCode {
+ /// \brief An ExtQualType record.
+ TYPE_EXT_QUAL = 1,
+ /// \brief A FixedWidthIntType record.
+ TYPE_FIXED_WIDTH_INT = 2,
+ /// \brief A ComplexType record.
+ TYPE_COMPLEX = 3,
+ /// \brief A PointerType record.
+ TYPE_POINTER = 4,
+ /// \brief A BlockPointerType record.
+ TYPE_BLOCK_POINTER = 5,
+ /// \brief An LValueReferenceType record.
+ TYPE_LVALUE_REFERENCE = 6,
+ /// \brief An RValueReferenceType record.
+ TYPE_RVALUE_REFERENCE = 7,
+ /// \brief A MemberPointerType record.
+ TYPE_MEMBER_POINTER = 8,
+ /// \brief A ConstantArrayType record.
+ TYPE_CONSTANT_ARRAY = 9,
+ /// \brief An IncompleteArrayType record.
+ TYPE_INCOMPLETE_ARRAY = 10,
+ /// \brief A VariableArrayType record.
+ TYPE_VARIABLE_ARRAY = 11,
+ /// \brief A VectorType record.
+ TYPE_VECTOR = 12,
+ /// \brief An ExtVectorType record.
+ TYPE_EXT_VECTOR = 13,
+ /// \brief A FunctionNoProtoType record.
+ TYPE_FUNCTION_NO_PROTO = 14,
+ /// \brief A FunctionProtoType record.
+ TYPE_FUNCTION_PROTO = 15,
+ /// \brief A TypedefType record.
+ TYPE_TYPEDEF = 16,
+ /// \brief A TypeOfExprType record.
+ TYPE_TYPEOF_EXPR = 17,
+ /// \brief A TypeOfType record.
+ TYPE_TYPEOF = 18,
+ /// \brief A RecordType record.
+ TYPE_RECORD = 19,
+ /// \brief An EnumType record.
+ TYPE_ENUM = 20,
+ /// \brief An ObjCInterfaceType record.
+ TYPE_OBJC_INTERFACE = 21,
+ /// \brief An ObjCQualifiedInterfaceType record.
+ TYPE_OBJC_QUALIFIED_INTERFACE = 22,
+ /// \brief An ObjCQualifiedIdType record.
+ TYPE_OBJC_QUALIFIED_ID = 23,
+ /// \brief An ObjCQualifiedClassType record.
+ TYPE_OBJC_QUALIFIED_CLASS = 24
+ };
+
+ /// \brief Record code for the offsets of each type.
+ ///
+ /// The TYPE_OFFSET constant describes the record that occurs
+ /// within the block identified by TYPE_OFFSETS_BLOCK_ID within
+ /// the PCH file. The record itself is an array of offsets that
+ /// point into the types block (identified by TYPES_BLOCK_ID in
+ /// the PCH file). The index into the array is based on the ID of
+ /// a type. For a given type ID @c T, the lower three bits of @c T
+ /// are its qualifiers (const, volatile, restrict), as in the
+ /// QualType class. The upper bits, after being shifted and
+ /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
+ /// TYPE_OFFSET block to determine the offset of that type's
+ /// corresponding record within the TYPES_BLOCK_ID block.
+ enum TypeOffsetCode {
+ TYPE_OFFSET = 1
+ };
+
+ /// \brief Record codes for each kind of declaration.
+ ///
+ /// These constants describe the records that can occur within a
+ /// declarations block (identified by DECLS_BLOCK_ID). Each
+ /// constant describes a record for a specific declaration class
+ /// in the AST.
+ enum DeclCode {
+ /// \brief A TranslationUnitDecl record.
+ DECL_TRANSLATION_UNIT = 1,
+ /// \brief A TypedefDecl record.
+ DECL_TYPEDEF,
+ /// \brief A VarDecl record.
+ DECL_VAR,
+ /// \brief A record that stores the set of declarations that are
+ /// lexically stored within a given DeclContext.
+ ///
+ /// The record itself is an array of declaration IDs, in the
+ /// order in which those declarations were added to the
+ /// declaration context. This data is used when iterating over
+ /// the contents of a DeclContext, e.g., via
+ /// DeclContext::decls_begin()/DeclContext::decls_end().
+ DECL_CONTEXT_LEXICAL,
+ /// \brief A record that stores the set of declarations that are
+ /// visible from a given DeclContext.
+ ///
+ /// The record itself stores a set of mappings, each of which
+ /// associates a declaration name with one or more declaration
+ /// IDs. This data is used when performing qualified name lookup
+ /// into a DeclContext via DeclContext::lookup.
+ DECL_CONTEXT_VISIBLE
+ };
+
+ /// \brief Record code for the offsets of each decl.
+ ///
+ /// The DECL_OFFSET constant describes the record that occurs
+ /// within the block identifier by DECL_OFFSETS_BLOCK_ID within
+ /// the PCH file. The record itself is an array of offsets that
+ /// point into the declarations block (identified by
+ /// DECLS_BLOCK_ID). The declaration ID is an index into this
+ /// record, after subtracting one to account for the use of
+ /// declaration ID 0 for a NULL declaration pointer. Index 0 is
+ /// reserved for the translation unit declaration.
+ enum DeclOffsetCode {
+ DECL_OFFSET = 1
+ };
+ }
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
new file mode 100644
index 0000000000..1338d3c03b
--- /dev/null
+++ b/include/clang/Frontend/PCHReader.h
@@ -0,0 +1,169 @@
+//===--- PCHReader.h - Precompiled Headers Reader ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PCHReader class, which reads a precompiled header.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_PCH_READER_H
+#define LLVM_CLANG_FRONTEND_PCH_READER_H
+
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/DataTypes.h"
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class DeclContext;
+
+/// \brief Reads a precompiled head containing the contents of a
+/// translation unit.
+///
+/// The PCHReader class reads a bitstream (produced by the PCHWriter
+/// class) containing the serialized representation of a given
+/// abstract syntax tree and its supporting data structures. An
+/// instance of the PCHReader can be attached to an ASTContext object,
+/// which will provide access to the contents of the PCH file.
+///
+/// The PCH reader provides lazy de-serialization of declarations, as
+/// required when traversing the AST. Only those AST nodes that are
+/// actually required will be de-serialized.
+class PCHReader : public ExternalASTSource {
+ /// \brief The AST context into which we'll read the PCH file.
+ ASTContext &Context;
+
+ /// \brief The bitstream reader from which we'll read the PCH file.
+ llvm::BitstreamReader Stream;
+
+ /// \brief The memory buffer that stores the data associated with
+ /// this PCH file.
+ llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+
+ /// \brief Offset of each type within the bitstream, indexed by the
+ /// type ID, or the representation of a Type*.
+ llvm::SmallVector<uint64_t, 16> TypeOffsets;
+
+ /// \brief Whether the type with a given index has already been loaded.
+ ///
+ /// When the bit at a given index I is true, then TypeOffsets[I] is
+ /// the already-loaded Type*. Otherwise, TypeOffsets[I] is the
+ /// location of the type's record in the PCH file.
+ ///
+ /// FIXME: We can probably eliminate this, e.g., by bitmangling the
+ /// values in TypeOffsets.
+ std::vector<bool> TypeAlreadyLoaded;
+
+ /// \brief Offset of each declaration within the bitstream, indexed
+ /// by the declaration ID.
+ llvm::SmallVector<uint64_t, 16> DeclOffsets;
+
+ /// \brief Whether the declaration with a given index has already
+ /// been loaded.
+ ///
+ /// When the bit at the given index I is true, then DeclOffsets[I]
+ /// is the already-loaded Decl*. Otherwise, DeclOffsets[I] is the
+ /// location of the declaration's record in the PCH file.
+ ///
+ /// FIXME: We can probably eliminate this, e.g., by bitmangling the
+ /// values in DeclOffsets.
+ std::vector<bool> DeclAlreadyLoaded;
+
+ typedef llvm::DenseMap<const DeclContext *, std::pair<uint64_t, uint64_t> >
+ DeclContextOffsetsMap;
+
+ /// \brief Offsets of the lexical and visible declarations for each
+ /// DeclContext.
+ DeclContextOffsetsMap DeclContextOffsets;
+
+ bool ReadPCHBlock();
+ bool ReadTypeOffsets();
+ bool ReadDeclOffsets();
+
+ QualType ReadTypeRecord(uint64_t Offset);
+ void LoadedDecl(unsigned Index, Decl *D);
+ Decl *ReadDeclRecord(uint64_t Offset, unsigned Index);
+
+ PCHReader(const PCHReader&); // do not implement
+ PCHReader &operator=(const PCHReader &); // do not implement
+
+public:
+ typedef llvm::SmallVector<uint64_t, 64> RecordData;
+
+ PCHReader(ASTContext &Context) : Context(Context), Buffer() { }
+ ~PCHReader();
+
+ bool ReadPCH(const std::string &FileName);
+
+ /// \brief Resolve a type ID into a type, potentially building a new
+ /// type.
+ virtual QualType GetType(unsigned ID);
+
+ /// \brief Resolve a declaration ID into a declaration, potentially