aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/PCHWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend/PCHWriter.cpp')
-rw-r--r--lib/Frontend/PCHWriter.cpp636
1 files changed, 636 insertions, 0 deletions
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
new file mode 100644
index 0000000000..39936b34f5
--- /dev/null
+++ b/lib/Frontend/PCHWriter.cpp
@@ -0,0 +1,636 @@
+//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- 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 PCHWriter class, which writes a precompiled header.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PCHWriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Type.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Type serialization
+//===----------------------------------------------------------------------===//
+namespace {
+ class VISIBILITY_HIDDEN PCHTypeWriter {
+ PCHWriter &Writer;
+ PCHWriter::RecordData &Record;
+
+ public:
+ /// \brief Type code that corresponds to the record generated.
+ pch::TypeCode Code;
+
+ PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+ : Writer(Writer), Record(Record) { }
+
+ void VisitArrayType(const ArrayType *T);
+ void VisitFunctionType(const FunctionType *T);
+ void VisitTagType(const TagType *T);
+
+#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ };
+}
+
+void PCHTypeWriter::VisitExtQualType(const ExtQualType *T) {
+ Writer.AddTypeRef(QualType(T->getBaseType(), 0), Record);
+ Record.push_back(T->getObjCGCAttr()); // FIXME: use stable values
+ Record.push_back(T->getAddressSpace());
+ Code = pch::TYPE_EXT_QUAL;
+}
+
+void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
+ assert(false && "Built-in types are never serialized");
+}
+
+void PCHTypeWriter::VisitFixedWidthIntType(const FixedWidthIntType *T) {
+ Record.push_back(T->getWidth());
+ Record.push_back(T->isSigned());
+ Code = pch::TYPE_FIXED_WIDTH_INT;
+}
+
+void PCHTypeWriter::VisitComplexType(const ComplexType *T) {
+ Writer.AddTypeRef(T->getElementType(), Record);
+ Code = pch::TYPE_COMPLEX;
+}
+
+void PCHTypeWriter::VisitPointerType(const PointerType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = pch::TYPE_POINTER;
+}
+
+void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = pch::TYPE_BLOCK_POINTER;
+}
+
+void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = pch::TYPE_LVALUE_REFERENCE;
+}
+
+void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = pch::TYPE_RVALUE_REFERENCE;
+}
+
+void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
+ Code = pch::TYPE_MEMBER_POINTER;
+}
+
+void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
+ Writer.AddTypeRef(T->getElementType(), Record);
+ Record.push_back(T->getSizeModifier()); // FIXME: stable values
+ Record.push_back(T->getIndexTypeQualifier()); // FIXME: stable values
+}
+
+void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
+ VisitArrayType(T);
+ Writer.AddAPInt(T->getSize(), Record);
+ Code = pch::TYPE_CONSTANT_ARRAY;
+}
+
+void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
+ VisitArrayType(T);
+ Code = pch::TYPE_INCOMPLETE_ARRAY;
+}
+
+void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
+ VisitArrayType(T);
+ // FIXME: Serialize array size expression.
+ assert(false && "Cannot serialize variable-length arrays");
+ Code = pch::TYPE_VARIABLE_ARRAY;
+}
+
+void PCHTypeWriter::VisitVectorType(const VectorType *T) {
+ Writer.AddTypeRef(T->getElementType(), Record);
+ Record.push_back(T->getNumElements());
+ Code = pch::TYPE_VECTOR;
+}
+
+void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
+ VisitVectorType(T);
+ Code = pch::TYPE_EXT_VECTOR;
+}
+
+void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
+ Writer.AddTypeRef(T->getResultType(), Record);
+}
+
+void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
+ VisitFunctionType(T);
+ Code = pch::TYPE_FUNCTION_NO_PROTO;
+}
+
+void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
+ VisitFunctionType(T);
+ Record.push_back(T->getNumArgs());
+ for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
+ Writer.AddTypeRef(T->getArgType(I), Record);
+ Record.push_back(T->isVariadic());
+ Record.push_back(T->getTypeQuals());
+ Code = pch::TYPE_FUNCTION_PROTO;
+}
+
+void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ Code = pch::TYPE_TYPEDEF;
+}
+
+void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
+ // FIXME: serialize the typeof expression
+ assert(false && "Cannot serialize typeof(expr)");
+ Code = pch::TYPE_TYPEOF_EXPR;
+}
+
+void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) {
+ Writer.AddTypeRef(T->getUnderlyingType(), Record);
+ Code = pch::TYPE_TYPEOF;
+}
+
+void PCHTypeWriter::VisitTagType(const TagType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ assert(!T->isBeingDefined() &&
+ "Cannot serialize in the middle of a type definition");
+}
+
+void PCHTypeWriter::VisitRecordType(const RecordType *T) {
+ VisitTagType(T);
+ Code = pch::TYPE_RECORD;
+}
+
+void PCHTypeWriter::VisitEnumType(const EnumType *T) {
+ VisitTagType(T);
+ Code = pch::TYPE_ENUM;
+}
+
+void
+PCHTypeWriter::VisitTemplateSpecializationType(
+ const TemplateSpecializationType *T) {
+ // FIXME: Serialize this type
+ assert(false && "Cannot serialize template specialization types");
+}
+
+void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) {
+ // FIXME: Serialize this type
+ assert(false && "Cannot serialize qualified name types");
+}
+
+void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ Code = pch::TYPE_OBJC_INTERFACE;
+}
+
+void
+PCHTypeWriter::VisitObjCQualifiedInterfaceType(
+ const ObjCQualifiedInterfaceType *T) {
+ VisitObjCInterfaceType(T);
+ Record.push_back(T->getNumProtocols());
+ for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
+ Writer.AddDeclRef(T->getProtocol(I), Record);
+ Code = pch::TYPE_OBJC_QUALIFIED_INTERFACE;
+}
+
+void PCHTypeWriter::VisitObjCQualifiedIdType(const ObjCQualifiedIdType *T) {
+ Record.push_back(T->getNumProtocols());
+ for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
+ Writer.AddDeclRef(T->getProtocols(I), Record);
+ Code = pch::TYPE_OBJC_QUALIFIED_ID;
+}
+
+void
+PCHTypeWriter::VisitObjCQualifiedClassType(const ObjCQualifiedClassType *T) {
+ Record.push_back(T->getNumProtocols());
+ for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
+ Writer.AddDeclRef(T->getProtocols(I), Record);
+ Code = pch::TYPE_OBJC_QUALIFIED_CLASS;
+}
+
+//===----------------------------------------------------------------------===//
+// Declaration serialization
+//===----------------------------------------------------------------------===//
+namespace {
+ class VISIBILITY_HIDDEN PCHDeclWriter
+ : public DeclVisitor<PCHDeclWriter, void> {
+
+ PCHWriter &Writer;
+ PCHWriter::RecordData &Record;
+
+ public:
+ pch::DeclCode Code;
+
+ PCHDeclWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+ : Writer(Writer), Record(Record) { }
+
+ void VisitDecl(Decl *D);
+ void VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ void VisitNamedDecl(NamedDecl *D);
+ void VisitTypeDecl(TypeDecl *D);
+ void VisitTypedefDecl(TypedefDecl *D);
+ void VisitValueDecl(ValueDecl *D);
+ void VisitVarDecl(VarDecl *D);
+
+ void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
+ uint64_t VisibleOffset);
+ };
+}
+
+void PCHDeclWriter::VisitDecl(Decl *D) {
+ Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
+ Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
+ Writer.AddSourceLocation(D->getLocation(), Record);
+ Record.push_back(D->isInvalidDecl());
+ // FIXME: hasAttrs
+ Record.push_back(D->isImplicit());
+ Record.push_back(D->getAccess());
+}
+
+void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ VisitDecl(D);
+ Code = pch::DECL_TRANSLATION_UNIT;
+}
+
+void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
+ VisitDecl(D);
+ Writer.AddDeclarationName(D->getDeclName(), Record);
+}
+
+void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
+}
+
+void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
+ VisitTypeDecl(D);
+ Writer.AddTypeRef(D->getUnderlyingType(), Record);
+ Code = pch::DECL_TYPEDEF;
+}
+
+void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddTypeRef(D->getType(), Record);
+}
+
+void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
+ VisitValueDecl(D);
+ Record.push_back(D->getStorageClass());
+ Record.push_back(D->isThreadSpecified());
+ Record.push_back(D->hasCXXDirectInitializer());
+ Record.push_back(D->isDeclaredInCondition());
+ Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
+ // FIXME: emit initializer
+ Code = pch::DECL_VAR;
+}
+
+/// \brief Emit the DeclContext part of a declaration context decl.
+///
+/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
+/// block for this declaration context is stored. May be 0 to indicate
+/// that there are no declarations stored within this context.
+///
+/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
+/// block for this declaration context is stored. May be 0 to indicate
+/// that there are no declarations visible from this context. Note
+/// that this value will not be emitted for non-primary declaration
+/// contexts.
+void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
+ uint64_t VisibleOffset) {
+ Record.push_back(LexicalOffset);
+ if (DC->getPrimaryContext() == DC)
+ Record.push_back(VisibleOffset);
+}
+
+//===----------------------------------------------------------------------===//
+// PCHWriter Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Write the representation of a type to the PCH stream.
+void PCHWriter::WriteType(const Type *T) {
+ pch::ID &ID = TypeIDs[T];
+ if (ID == 0) // we haven't seen this type before
+ ID = NextTypeID++;
+
+ // Record the offset for this type.
+ if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS)
+ TypeOffsets.push_back(S.GetCurrentBitNo());
+ else if (TypeOffsets.size() < ID - pch::NUM_PREDEF_TYPE_IDS) {
+ TypeOffsets.resize(ID + 1 - pch::NUM_PREDEF_TYPE_IDS);
+ TypeOffsets[ID - pch::NUM_PREDEF_TYPE_IDS] = S.GetCurrentBitNo();
+ }
+
+ RecordData Record;
+
+ // Emit the type's representation.
+ PCHTypeWriter W(*this, Record);
+ switch (T->getTypeClass()) {
+ // For all of the concrete, non-dependent types, call the
+ // appropriate visitor function.
+#define TYPE(Class, Base) \
+ case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+
+ // For all of the dependent type nodes (which only occur in C++
+ // templates), produce an error.
+#define TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Cannot serialize dependent type nodes");
+ break;
+ }
+
+ // Emit the serialized record.
+ S.EmitRecord(W.Code, Record);
+}
+
+/// \brief Write a block containing all of the types.
+void PCHWriter::WriteTypesBlock(ASTContext &Context) {
+ // Enter the types block
+ S.EnterSubblock(pch::TYPES_BLOCK_ID, 2);
+
+ // Emit all of the types in the ASTContext
+ for (std::vector<Type*>::const_iterator T = Context.getTypes().begin(),
+ TEnd = Context.getTypes().end();
+ T != TEnd; ++T) {
+ // Builtin types are never serialized.
+ if (isa<BuiltinType>(*T))
+ continue;
+
+ WriteType(*T);
+ }
+
+ // Exit the types block
+ S.ExitBlock();
+
+ // Write the type offsets block
+ S.EnterSubblock(pch::TYPE_OFFSETS_BLOCK_ID, 2);
+ S.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
+ S.ExitBlock();
+}
+
+/// \brief Write the block containing all of the declaration IDs
+/// lexically declared within the given DeclContext.
+///
+/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
+/// bistream, or 0 if no block was written.
+uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
+ DeclContext *DC) {
+ if (DC->decls_begin(Context) == DC->decls_end(Context))
+ return 0;
+
+ uint64_t Offset = S.GetCurrentBitNo();
+ RecordData Record;
+ for (DeclContext::decl_iterator D = DC->decls_begin(Context),
+ DEnd = DC->decls_end(Context);
+ D != DEnd; ++D)
+ AddDeclRef(*D, Record);
+
+ S.EmitRecord(pch::DECL_CONTEXT_LEXICAL, Record);
+ return Offset;
+}
+
+/// \brief Write the block containing all of the declaration IDs
+/// visible from the given DeclContext.
+///
+/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
+/// bistream, or 0 if no block was written.
+uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
+ DeclContext *DC) {
+ if (DC->getPrimaryContext() != DC)
+ return 0;
+
+ // Force the DeclContext to build a its name-lookup table.
+ DC->lookup(Context, DeclarationName());
+
+ // Serialize the contents of the mapping used for lookup. Note that,
+ // although we have two very different code paths, the serialized
+ // representation is the same for both cases: a declaration name,
+ // followed by a size, followed by references to the visible
+ // declarations that have that name.
+ uint64_t Offset = S.GetCurrentBitNo();
+ RecordData Record;
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+ for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
+ D != DEnd; ++D) {
+ AddDeclarationName(D->first, Record);
+ DeclContext::lookup_result Result = D->second.getLookupResult(Context);
+ Record.push_back(Result.second - Result.first);
+ for(; Result.first != Result.second; ++Result.first)
+ AddDeclRef(*Result.first, Record);
+ }
+
+ if (Record.size() == 0)
+ return 0;
+
+ S.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record);
+ return Offset;
+}
+
+/// \brief Write a block containing all of the declarations.
+void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
+ // Enter the declarations block
+ S.EnterSubblock(pch::DECLS_BLOCK_ID, 2);
+
+ // Emit all of the declarations.
+ RecordData Record;
+ PCHDeclWriter W(*this, Record);
+ while (!DeclsToEmit.empty()) {
+ // Pull the next declaration off the queue
+ Decl *D = DeclsToEmit.front();
+ DeclsToEmit.pop();
+
+ // If this declaration is also a DeclContext, write blocks for the
+ // declarations that lexically stored inside its context and those
+ // declarations that are visible from its context. These blocks
+ // are written before the declaration itself so that we can put
+ // their offsets into the record for the declaration.
+ uint64_t LexicalOffset = 0;
+ uint64_t VisibleOffset = 0;
+ DeclContext *DC = dyn_cast<DeclContext>(D);
+ if (DC) {
+ LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
+ VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
+ }
+
+ // Determine the ID for this declaration
+ pch::ID ID = DeclIDs[D];
+ if (ID == 0)
+ ID = DeclIDs.size();
+
+ unsigned Index = ID - 1;
+
+ // Record the offset for this declaration
+ if (DeclOffsets.size() == Index)
+ DeclOffsets.push_back(S.GetCurrentBitNo());
+ else if (DeclOffsets.size() < Index) {
+ DeclOffsets.resize(Index+1);
+ DeclOffsets[Index] = S.GetCurrentBitNo();
+ }
+
+ // Build and emit a record for this declaration
+ Record.clear();
+ W.Code = (pch::DeclCode)0;
+ W.Visit(D);
+ if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
+ assert(W.Code && "Visitor did not set record code");
+ S.EmitRecord(W.Code, Record);
+ }
+
+ // Exit the declarations block
+ S.ExitBlock();
+
+ // Write the declaration offsets block
+ S.EnterSubblock(pch::DECL_OFFSETS_BLOCK_ID, 2);
+ S.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
+ S.ExitBlock();
+}
+
+PCHWriter::PCHWriter(llvm::BitstreamWriter &S)
+ : S(S), NextTypeID(pch::NUM_PREDEF_TYPE_IDS) { }
+
+void PCHWriter::WritePCH(ASTContext &Context) {
+ // Emit the file header.
+ S.Emit((unsigned)'C', 8);
+ S.Emit((unsigned)'P', 8);
+ S.Emit((unsigned)'C', 8);
+ S.Emit((unsigned)'H', 8);
+
+ // The translation unit is the first declaration we'll emit.
+ DeclIDs[Context.getTranslationUnitDecl()] = 1;
+ DeclsToEmit.push(Context.getTranslationUnitDecl());
+
+ // Write the remaining PCH contents.
+ S.EnterSubblock(pch::PCH_BLOCK_ID, 2);
+ WriteTypesBlock(Context);
+ WriteDeclsBlock(Context);
+ S.ExitBlock();
+}
+
+void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
+ Record.push_back(Loc.getRawEncoding());
+}
+
+void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
+ Record.push_back(Value.getBitWidth());
+ unsigned N = Value.getNumWords();
+ const uint64_t* Words = Value.getRawData();
+ for (unsigned I = 0; I != N; ++I)
+ Record.push_back(Words[I]);
+}
+
+void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
+ // FIXME: Emit an identifier ID, not the actual string!
+ const char *Name = II->getName();
+ unsigned Len = strlen(Name);
+ Record.push_back(Len);
+ Record.insert(Record.end(), Name, Name + Len);
+}
+
+void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
+ if (T.isNull()) {
+ Record.push_back(pch::PREDEF_TYPE_NULL_ID);
+ return;
+ }
+
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
+ pch::ID ID;
+ switch (BT->getKind()) {
+ case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break;
+ case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break;
+ case BuiltinType::Char_U: ID = pch::PREDEF_TYPE_CHAR_U_ID; break;
+ case BuiltinType::UChar: ID = pch::PREDEF_TYPE_UCHAR_ID; break;
+ case BuiltinType::UShort: ID = pch::PREDEF_TYPE_USHORT_ID; break;
+ case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break;
+ case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break;
+ case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break;
+ case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break;
+ case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break;
+ case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break;
+ case BuiltinType::Short: ID = pch::PREDEF_TYPE_SHORT_ID; break;
+ case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break;
+ case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break;
+ case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break;
+ case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break;
+ case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break;
+ case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
+ case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break;
+ case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
+ }
+
+ Record.push_back((ID << 3) | T.getCVRQualifiers());
+ return;
+ }
+
+ pch::ID &ID = TypeIDs[T.getTypePtr()];
+ if (ID == 0) // we haven't seen this type before
+ ID = NextTypeID++;
+
+ // Encode the type qualifiers in the type reference.
+ Record.push_back((ID << 3) | T.getCVRQualifiers());
+}
+
+void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
+ if (D == 0) {
+ Record.push_back(0);
+ return;
+ }
+
+ pch::ID &ID = DeclIDs[D];
+ if (ID == 0) {
+ // We haven't seen this declaration before. Give it a new ID and
+ // enqueue it in the list of declarations to emit.
+ ID = DeclIDs.size();
+ DeclsToEmit.push(const_cast<Decl *>(D));
+ }
+
+ Record.push_back(ID);
+}
+
+void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
+ Record.push_back(Name.getNameKind());
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ AddIdentifierRef(Name.getAsIdentifierInfo(), Record);
+ break;
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ assert(false && "Serialization of Objective-C selectors unavailable");
+ break;
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ AddTypeRef(Name.getCXXNameType(), Record);
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ Record.push_back(Name.getCXXOverloadedOperator());
+ break;
+
+ case DeclarationName::CXXUsingDirective:
+ // No extra data to emit
+ break;
+ }
+}