blob: 6758a506998d4747bc9aacf900c99cf37b0e84f1 [file] [log] [blame]
Douglas Gregor2cf26342009-04-09 22:27:44 +00001//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the PCHWriter class, which writes a precompiled header.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Frontend/PCHWriter.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclContextInternals.h"
18#include "clang/AST/DeclVisitor.h"
19#include "clang/AST/Type.h"
Chris Lattner7c5d24e2009-04-10 18:00:12 +000020#include "clang/Lex/MacroInfo.h"
21#include "clang/Lex/Preprocessor.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000022#include "clang/Basic/FileManager.h"
23#include "clang/Basic/SourceManager.h"
Douglas Gregorbd945002009-04-13 16:31:14 +000024#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregor2bec0412009-04-10 21:16:55 +000025#include "clang/Basic/TargetInfo.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000026#include "llvm/Bitcode/BitstreamWriter.h"
27#include "llvm/Support/Compiler.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000028#include "llvm/Support/MemoryBuffer.h"
Chris Lattner3c304bd2009-04-11 18:40:46 +000029#include <cstdio>
Douglas Gregor2cf26342009-04-09 22:27:44 +000030using namespace clang;
31
32//===----------------------------------------------------------------------===//
33// Type serialization
34//===----------------------------------------------------------------------===//
35namespace {
36 class VISIBILITY_HIDDEN PCHTypeWriter {
37 PCHWriter &Writer;
38 PCHWriter::RecordData &Record;
39
40 public:
41 /// \brief Type code that corresponds to the record generated.
42 pch::TypeCode Code;
43
44 PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
45 : Writer(Writer), Record(Record) { }
46
47 void VisitArrayType(const ArrayType *T);
48 void VisitFunctionType(const FunctionType *T);
49 void VisitTagType(const TagType *T);
50
51#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
52#define ABSTRACT_TYPE(Class, Base)
53#define DEPENDENT_TYPE(Class, Base)
54#include "clang/AST/TypeNodes.def"
55 };
56}
57
58void PCHTypeWriter::VisitExtQualType(const ExtQualType *T) {
59 Writer.AddTypeRef(QualType(T->getBaseType(), 0), Record);
60 Record.push_back(T->getObjCGCAttr()); // FIXME: use stable values
61 Record.push_back(T->getAddressSpace());
62 Code = pch::TYPE_EXT_QUAL;
63}
64
65void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
66 assert(false && "Built-in types are never serialized");
67}
68
69void PCHTypeWriter::VisitFixedWidthIntType(const FixedWidthIntType *T) {
70 Record.push_back(T->getWidth());
71 Record.push_back(T->isSigned());
72 Code = pch::TYPE_FIXED_WIDTH_INT;
73}
74
75void PCHTypeWriter::VisitComplexType(const ComplexType *T) {
76 Writer.AddTypeRef(T->getElementType(), Record);
77 Code = pch::TYPE_COMPLEX;
78}
79
80void PCHTypeWriter::VisitPointerType(const PointerType *T) {
81 Writer.AddTypeRef(T->getPointeeType(), Record);
82 Code = pch::TYPE_POINTER;
83}
84
85void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
86 Writer.AddTypeRef(T->getPointeeType(), Record);
87 Code = pch::TYPE_BLOCK_POINTER;
88}
89
90void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
91 Writer.AddTypeRef(T->getPointeeType(), Record);
92 Code = pch::TYPE_LVALUE_REFERENCE;
93}
94
95void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
96 Writer.AddTypeRef(T->getPointeeType(), Record);
97 Code = pch::TYPE_RVALUE_REFERENCE;
98}
99
100void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
101 Writer.AddTypeRef(T->getPointeeType(), Record);
102 Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
103 Code = pch::TYPE_MEMBER_POINTER;
104}
105
106void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
107 Writer.AddTypeRef(T->getElementType(), Record);
108 Record.push_back(T->getSizeModifier()); // FIXME: stable values
109 Record.push_back(T->getIndexTypeQualifier()); // FIXME: stable values
110}
111
112void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
113 VisitArrayType(T);
114 Writer.AddAPInt(T->getSize(), Record);
115 Code = pch::TYPE_CONSTANT_ARRAY;
116}
117
118void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
119 VisitArrayType(T);
120 Code = pch::TYPE_INCOMPLETE_ARRAY;
121}
122
123void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
124 VisitArrayType(T);
125 // FIXME: Serialize array size expression.
126 assert(false && "Cannot serialize variable-length arrays");
127 Code = pch::TYPE_VARIABLE_ARRAY;
128}
129
130void PCHTypeWriter::VisitVectorType(const VectorType *T) {
131 Writer.AddTypeRef(T->getElementType(), Record);
132 Record.push_back(T->getNumElements());
133 Code = pch::TYPE_VECTOR;
134}
135
136void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
137 VisitVectorType(T);
138 Code = pch::TYPE_EXT_VECTOR;
139}
140
141void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
142 Writer.AddTypeRef(T->getResultType(), Record);
143}
144
145void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
146 VisitFunctionType(T);
147 Code = pch::TYPE_FUNCTION_NO_PROTO;
148}
149
150void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
151 VisitFunctionType(T);
152 Record.push_back(T->getNumArgs());
153 for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
154 Writer.AddTypeRef(T->getArgType(I), Record);
155 Record.push_back(T->isVariadic());
156 Record.push_back(T->getTypeQuals());
157 Code = pch::TYPE_FUNCTION_PROTO;
158}
159
160void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
161 Writer.AddDeclRef(T->getDecl(), Record);
162 Code = pch::TYPE_TYPEDEF;
163}
164
165void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
166 // FIXME: serialize the typeof expression
167 assert(false && "Cannot serialize typeof(expr)");
168 Code = pch::TYPE_TYPEOF_EXPR;
169}
170
171void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) {
172 Writer.AddTypeRef(T->getUnderlyingType(), Record);
173 Code = pch::TYPE_TYPEOF;
174}
175
176void PCHTypeWriter::VisitTagType(const TagType *T) {
177 Writer.AddDeclRef(T->getDecl(), Record);
178 assert(!T->isBeingDefined() &&
179 "Cannot serialize in the middle of a type definition");
180}
181
182void PCHTypeWriter::VisitRecordType(const RecordType *T) {
183 VisitTagType(T);
184 Code = pch::TYPE_RECORD;
185}
186
187void PCHTypeWriter::VisitEnumType(const EnumType *T) {
188 VisitTagType(T);
189 Code = pch::TYPE_ENUM;
190}
191
192void
193PCHTypeWriter::VisitTemplateSpecializationType(
194 const TemplateSpecializationType *T) {
195 // FIXME: Serialize this type
196 assert(false && "Cannot serialize template specialization types");
197}
198
199void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) {
200 // FIXME: Serialize this type
201 assert(false && "Cannot serialize qualified name types");
202}
203
204void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
205 Writer.AddDeclRef(T->getDecl(), Record);
206 Code = pch::TYPE_OBJC_INTERFACE;
207}
208
209void
210PCHTypeWriter::VisitObjCQualifiedInterfaceType(
211 const ObjCQualifiedInterfaceType *T) {
212 VisitObjCInterfaceType(T);
213 Record.push_back(T->getNumProtocols());
214 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
215 Writer.AddDeclRef(T->getProtocol(I), Record);
216 Code = pch::TYPE_OBJC_QUALIFIED_INTERFACE;
217}
218
219void PCHTypeWriter::VisitObjCQualifiedIdType(const ObjCQualifiedIdType *T) {
220 Record.push_back(T->getNumProtocols());
221 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
222 Writer.AddDeclRef(T->getProtocols(I), Record);
223 Code = pch::TYPE_OBJC_QUALIFIED_ID;
224}
225
226void
227PCHTypeWriter::VisitObjCQualifiedClassType(const ObjCQualifiedClassType *T) {
228 Record.push_back(T->getNumProtocols());
229 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
230 Writer.AddDeclRef(T->getProtocols(I), Record);
231 Code = pch::TYPE_OBJC_QUALIFIED_CLASS;
232}
233
234//===----------------------------------------------------------------------===//
235// Declaration serialization
236//===----------------------------------------------------------------------===//
237namespace {
238 class VISIBILITY_HIDDEN PCHDeclWriter
239 : public DeclVisitor<PCHDeclWriter, void> {
240
241 PCHWriter &Writer;
242 PCHWriter::RecordData &Record;
243
244 public:
245 pch::DeclCode Code;
246
247 PCHDeclWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
248 : Writer(Writer), Record(Record) { }
249
250 void VisitDecl(Decl *D);
251 void VisitTranslationUnitDecl(TranslationUnitDecl *D);
252 void VisitNamedDecl(NamedDecl *D);
253 void VisitTypeDecl(TypeDecl *D);
254 void VisitTypedefDecl(TypedefDecl *D);
Douglas Gregor0a2b45e2009-04-13 18:14:40 +0000255 void VisitTagDecl(TagDecl *D);
256 void VisitEnumDecl(EnumDecl *D);
Douglas Gregor8c700062009-04-13 21:20:57 +0000257 void VisitRecordDecl(RecordDecl *D);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000258 void VisitValueDecl(ValueDecl *D);
Douglas Gregor0a2b45e2009-04-13 18:14:40 +0000259 void VisitEnumConstantDecl(EnumConstantDecl *D);
Douglas Gregor8c700062009-04-13 21:20:57 +0000260 void VisitFieldDecl(FieldDecl *D);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000261 void VisitVarDecl(VarDecl *D);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000262 void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
263 uint64_t VisibleOffset);
264 };
265}
266
267void PCHDeclWriter::VisitDecl(Decl *D) {
268 Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
269 Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
270 Writer.AddSourceLocation(D->getLocation(), Record);
271 Record.push_back(D->isInvalidDecl());
272 // FIXME: hasAttrs
273 Record.push_back(D->isImplicit());
274 Record.push_back(D->getAccess());
275}
276
277void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
278 VisitDecl(D);
279 Code = pch::DECL_TRANSLATION_UNIT;
280}
281
282void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
283 VisitDecl(D);
284 Writer.AddDeclarationName(D->getDeclName(), Record);
285}
286
287void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
288 VisitNamedDecl(D);
289 Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
290}
291
292void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
293 VisitTypeDecl(D);
294 Writer.AddTypeRef(D->getUnderlyingType(), Record);
295 Code = pch::DECL_TYPEDEF;
296}
297
Douglas Gregor0a2b45e2009-04-13 18:14:40 +0000298void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
299 VisitTypeDecl(D);
300 Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
301 Record.push_back(D->isDefinition());
302 Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
303}
304
305void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
306 VisitTagDecl(D);
307 Writer.AddTypeRef(D->getIntegerType(), Record);
308 Code = pch::DECL_ENUM;
309}
310
Douglas Gregor8c700062009-04-13 21:20:57 +0000311void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
312 VisitTagDecl(D);
313 Record.push_back(D->hasFlexibleArrayMember());
314 Record.push_back(D->isAnonymousStructOrUnion());
315 Code = pch::DECL_RECORD;
316}
317
Douglas Gregor2cf26342009-04-09 22:27:44 +0000318void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
319 VisitNamedDecl(D);
320 Writer.AddTypeRef(D->getType(), Record);
321}
322
Douglas Gregor0a2b45e2009-04-13 18:14:40 +0000323void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
324 VisitValueDecl(D);
325 // FIXME: Writer.AddExprRef(D->getInitExpr());
326 Writer.AddAPSInt(D->getInitVal(), Record);
327 Code = pch::DECL_ENUM_CONSTANT;
328}
329
Douglas Gregor8c700062009-04-13 21:20:57 +0000330void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
331 VisitValueDecl(D);
332 Record.push_back(D->isMutable());
333 // FIXME: Writer.AddExprRef(D->getBitWidth());
334 Code = pch::DECL_FIELD;
335}
336
Douglas Gregor2cf26342009-04-09 22:27:44 +0000337void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
338 VisitValueDecl(D);
339 Record.push_back(D->getStorageClass());
340 Record.push_back(D->isThreadSpecified());
341 Record.push_back(D->hasCXXDirectInitializer());
342 Record.push_back(D->isDeclaredInCondition());
343 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
344 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
345 // FIXME: emit initializer
346 Code = pch::DECL_VAR;
347}
348
349/// \brief Emit the DeclContext part of a declaration context decl.
350///
351/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
352/// block for this declaration context is stored. May be 0 to indicate
353/// that there are no declarations stored within this context.
354///
355/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
356/// block for this declaration context is stored. May be 0 to indicate
357/// that there are no declarations visible from this context. Note
358/// that this value will not be emitted for non-primary declaration
359/// contexts.
360void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
361 uint64_t VisibleOffset) {
362 Record.push_back(LexicalOffset);
363 if (DC->getPrimaryContext() == DC)
364 Record.push_back(VisibleOffset);
365}
366
367//===----------------------------------------------------------------------===//
368// PCHWriter Implementation
369//===----------------------------------------------------------------------===//
370
Douglas Gregor2bec0412009-04-10 21:16:55 +0000371/// \brief Write the target triple (e.g., i686-apple-darwin9).
372void PCHWriter::WriteTargetTriple(const TargetInfo &Target) {
373 using namespace llvm;
374 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
375 Abbrev->Add(BitCodeAbbrevOp(pch::TARGET_TRIPLE));
376 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Triple name
377 unsigned TripleAbbrev = S.EmitAbbrev(Abbrev);
378
379 RecordData Record;
380 Record.push_back(pch::TARGET_TRIPLE);
381 const char *Triple = Target.getTargetTriple();
382 S.EmitRecordWithBlob(TripleAbbrev, Record, Triple, strlen(Triple));
383}
384
385/// \brief Write the LangOptions structure.
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000386void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
387 RecordData Record;
388 Record.push_back(LangOpts.Trigraphs);
389 Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments.
390 Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers.
391 Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode.
392 Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc)
393 Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'.
394 Record.push_back(LangOpts.Digraphs); // C94, C99 and C++
395 Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants.
396 Record.push_back(LangOpts.C99); // C99 Support
397 Record.push_back(LangOpts.Microsoft); // Microsoft extensions.
398 Record.push_back(LangOpts.CPlusPlus); // C++ Support
399 Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support
400 Record.push_back(LangOpts.NoExtensions); // All extensions are disabled, strict mode.
401 Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords.
402
403 Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled.
404 Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled.
405 Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C modern abi enabled
406
407 Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings
408 Record.push_back(LangOpts.Boolean); // Allow bool/true/false
409 Record.push_back(LangOpts.WritableStrings); // Allow writable strings
410 Record.push_back(LangOpts.LaxVectorConversions);
411 Record.push_back(LangOpts.Exceptions); // Support exception handling.
412
413 Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime.
414 Record.push_back(LangOpts.Freestanding); // Freestanding implementation
415 Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin)
416
417 Record.push_back(LangOpts.ThreadsafeStatics); // Whether static initializers are protected
418 // by locks.
419 Record.push_back(LangOpts.Blocks); // block extension to C
420 Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if
421 // they are unused.
422 Record.push_back(LangOpts.MathErrno); // Math functions must respect errno
423 // (modulo the platform support).
424
425 Record.push_back(LangOpts.OverflowChecking); // Extension to call a handler function when
426 // signed integer arithmetic overflows.
427
428 Record.push_back(LangOpts.HeinousExtensions); // Extensions that we really don't like and
429 // may be ripped out at any time.
430
431 Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined.
432 Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be
433 // defined.
434 Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as
435 // opposed to __DYNAMIC__).
436 Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero.
437
438 Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be
439 // used (instead of C99 semantics).
440 Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined.
441 Record.push_back(LangOpts.getGCMode());
442 Record.push_back(LangOpts.getVisibilityMode());
443 Record.push_back(LangOpts.InstantiationDepth);
444 S.EmitRecord(pch::LANGUAGE_OPTIONS, Record);
445}
446
Douglas Gregor14f79002009-04-10 03:52:48 +0000447//===----------------------------------------------------------------------===//
448// Source Manager Serialization
449//===----------------------------------------------------------------------===//
450
451/// \brief Create an abbreviation for the SLocEntry that refers to a
452/// file.
453static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &S) {
454 using namespace llvm;
455 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
456 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
457 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
458 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
459 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
460 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
461 // FIXME: Need an actual encoding for the line directives; maybe
462 // this should be an array?
463 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
464 return S.EmitAbbrev(Abbrev);
465}
466
467/// \brief Create an abbreviation for the SLocEntry that refers to a
468/// buffer.
469static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &S) {
470 using namespace llvm;
471 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
472 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
473 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
474 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
475 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
476 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
477 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
478 return S.EmitAbbrev(Abbrev);
479}
480
481/// \brief Create an abbreviation for the SLocEntry that refers to a
482/// buffer's blob.
483static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &S) {
484 using namespace llvm;
485 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
486 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
487 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
488 return S.EmitAbbrev(Abbrev);
489}
490
491/// \brief Create an abbreviation for the SLocEntry that refers to an
492/// buffer.
493static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &S) {
494 using namespace llvm;
495 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
496 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
497 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
498 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
499 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
500 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
501 return S.EmitAbbrev(Abbrev);
502}
503
504/// \brief Writes the block containing the serialized form of the
505/// source manager.
506///
507/// TODO: We should probably use an on-disk hash table (stored in a
508/// blob), indexed based on the file name, so that we only create
509/// entries for files that we actually need. In the common case (no
510/// errors), we probably won't have to create file entries for any of
511/// the files in the AST.
512void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) {
Chris Lattnerf04ad692009-04-10 17:16:57 +0000513 // Enter the source manager block.
Douglas Gregor14f79002009-04-10 03:52:48 +0000514 S.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
515
516 // Abbreviations for the various kinds of source-location entries.
517 int SLocFileAbbrv = -1;
518 int SLocBufferAbbrv = -1;
519 int SLocBufferBlobAbbrv = -1;
520 int SLocInstantiationAbbrv = -1;
521
522 // Write out the source location entry table. We skip the first
523 // entry, which is always the same dummy entry.
524 RecordData Record;
525 for (SourceManager::sloc_entry_iterator
526 SLoc = SourceMgr.sloc_entry_begin() + 1,
527 SLocEnd = SourceMgr.sloc_entry_end();
528 SLoc != SLocEnd; ++SLoc) {
529 // Figure out which record code to use.
530 unsigned Code;
531 if (SLoc->isFile()) {
532 if (SLoc->getFile().getContentCache()->Entry)
533 Code = pch::SM_SLOC_FILE_ENTRY;
534 else
535 Code = pch::SM_SLOC_BUFFER_ENTRY;
536 } else
537 Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
538 Record.push_back(Code);
539
540 Record.push_back(SLoc->getOffset());
541 if (SLoc->isFile()) {
542 const SrcMgr::FileInfo &File = SLoc->getFile();
543 Record.push_back(File.getIncludeLoc().getRawEncoding());
544 Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
Douglas Gregorbd945002009-04-13 16:31:14 +0000545 Record.push_back(File.hasLineDirectives());
Douglas Gregor14f79002009-04-10 03:52:48 +0000546
547 const SrcMgr::ContentCache *Content = File.getContentCache();
548 if (Content->Entry) {
549 // The source location entry is a file. The blob associated
550 // with this entry is the file name.
551 if (SLocFileAbbrv == -1)
552 SLocFileAbbrv = CreateSLocFileAbbrev(S);
553 S.EmitRecordWithBlob(SLocFileAbbrv, Record,
554 Content->Entry->getName(),
555 strlen(Content->Entry->getName()));
556 } else {
557 // The source location entry is a buffer. The blob associated
558 // with this entry contains the contents of the buffer.
559 if (SLocBufferAbbrv == -1) {
560 SLocBufferAbbrv = CreateSLocBufferAbbrev(S);
561 SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(S);
562 }
563
564 // We add one to the size so that we capture the trailing NULL
565 // that is required by llvm::MemoryBuffer::getMemBuffer (on
566 // the reader side).
567 const llvm::MemoryBuffer *Buffer = Content->getBuffer();
568 const char *Name = Buffer->getBufferIdentifier();
569 S.EmitRecordWithBlob(SLocBufferAbbrv, Record, Name, strlen(Name) + 1);
570 Record.clear();
571 Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
572 S.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
573 Buffer->getBufferStart(),
574 Buffer->getBufferSize() + 1);
575 }
576 } else {
577 // The source location entry is an instantiation.
578 const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
579 Record.push_back(Inst.getSpellingLoc().getRawEncoding());
580 Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
581 Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
582
583 if (SLocInstantiationAbbrv == -1)
584 SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(S);
585 S.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
586 }
587
588 Record.clear();
589 }
590
Douglas Gregorbd945002009-04-13 16:31:14 +0000591 // Write the line table.
592 if (SourceMgr.hasLineTable()) {
593 LineTableInfo &LineTable = SourceMgr.getLineTable();
594
595 // Emit the file names
596 Record.push_back(LineTable.getNumFilenames());
597 for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
598 // Emit the file name
599 const char *Filename = LineTable.getFilename(I);
600 unsigned FilenameLen = Filename? strlen(Filename) : 0;
601 Record.push_back(FilenameLen);
602 if (FilenameLen)
603 Record.insert(Record.end(), Filename, Filename + FilenameLen);
604 }
605
606 // Emit the line entries
607 for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
608 L != LEnd; ++L) {
609 // Emit the file ID
610 Record.push_back(L->first);
611
612 // Emit the line entries
613 Record.push_back(L->second.size());
614 for (std::vector<LineEntry>::iterator LE = L->second.begin(),
615 LEEnd = L->second.end();
616 LE != LEEnd; ++LE) {
617 Record.push_back(LE->FileOffset);
618 Record.push_back(LE->LineNo);
619 Record.push_back(LE->FilenameID);
620 Record.push_back((unsigned)LE->FileKind);
621 Record.push_back(LE->IncludeOffset);
622 }
623 S.EmitRecord(pch::SM_LINE_TABLE, Record);
624 }
625 }
626
Douglas Gregor14f79002009-04-10 03:52:48 +0000627 S.ExitBlock();
628}
629
Chris Lattner0b1fb982009-04-10 17:15:23 +0000630/// \brief Writes the block containing the serialized form of the
631/// preprocessor.
632///
Chris Lattnerdf961c22009-04-10 18:08:30 +0000633void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
Chris Lattnerf04ad692009-04-10 17:16:57 +0000634 // Enter the preprocessor block.
635 S.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 3);
636
Chris Lattner7c5d24e2009-04-10 18:00:12 +0000637 // If the PCH file contains __DATE__ or __TIME__ emit a warning about this.
638 // FIXME: use diagnostics subsystem for localization etc.
639 if (PP.SawDateOrTime())
640 fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
Chris Lattnerf04ad692009-04-10 17:16:57 +0000641
Chris Lattner7c5d24e2009-04-10 18:00:12 +0000642 RecordData Record;
Chris Lattnerf04ad692009-04-10 17:16:57 +0000643
Chris Lattnerc1f9d822009-04-13 01:29:17 +0000644 // If the preprocessor __COUNTER__ value has been bumped, remember it.
645 if (PP.getCounterValue() != 0) {
646 Record.push_back(PP.getCounterValue());
647 S.EmitRecord(pch::PP_COUNTER_VALUE, Record);
648 Record.clear();
649 }
650
Chris Lattner7c5d24e2009-04-10 18:00:12 +0000651 // Loop over all the macro definitions that are live at the end of the file,
652 // emitting each to the PP section.
653 // FIXME: Eventually we want to emit an index so that we can lazily load
654 // macros.
655 for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
656 I != E; ++I) {
Chris Lattner42d42b52009-04-10 21:41:48 +0000657 // FIXME: This emits macros in hash table order, we should do it in a stable
658 // order so that output is reproducible.
Chris Lattner7c5d24e2009-04-10 18:00:12 +0000659 MacroInfo *MI = I->second;
660
661 // Don't emit builtin macros like __LINE__ to the PCH file unless they have
662 // been redefined by the header (in which case they are not isBuiltinMacro).
663 if (MI->isBuiltinMacro())
664 continue;
665
Chris Lattner7356a312009-04-11 21:15:38 +0000666 AddIdentifierRef(I->first, Record);
Chris Lattner7c5d24e2009-04-10 18:00:12 +0000667 Record.push_back(MI->getDefinitionLoc().getRawEncoding());
668 Record.push_back(MI->isUsed());
669
670 unsigned Code;
671 if (MI->isObjectLike()) {
672 Code = pch::PP_MACRO_OBJECT_LIKE;
673 } else {
674 Code = pch::PP_MACRO_FUNCTION_LIKE;
675
676 Record.push_back(MI->isC99Varargs());
677 Record.push_back(MI->isGNUVarargs());
678 Record.push_back(MI->getNumArgs());
679 for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
680 I != E; ++I)
Chris Lattner7356a312009-04-11 21:15:38 +0000681 AddIdentifierRef(*I, Record);
Chris Lattner7c5d24e2009-04-10 18:00:12 +0000682 }
683 S.EmitRecord(Code, Record);
684 Record.clear();
685
Chris Lattnerdf961c22009-04-10 18:08:30 +0000686 // Emit the tokens array.
687 for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
688 // Note that we know that the preprocessor does not have any annotation
689 // tokens in it because they are created by the parser, and thus can't be
690 // in a macro definition.
691 const Token &Tok = MI->getReplacementToken(TokNo);
692
693 Record.push_back(Tok.getLocation().getRawEncoding());
694 Record.push_back(Tok.getLength());
695
Chris Lattnerdf961c22009-04-10 18:08:30 +0000696 // FIXME: When reading literal tokens, reconstruct the literal pointer if
697 // it is needed.
Chris Lattner7356a312009-04-11 21:15:38 +0000698 AddIdentifierRef(Tok.getIdentifierInfo(), Record);
Chris Lattnerdf961c22009-04-10 18:08:30 +0000699
700 // FIXME: Should translate token kind to a stable encoding.
701 Record.push_back(Tok.getKind());
702 // FIXME: Should translate token flags to a stable encoding.
703 Record.push_back(Tok.getFlags());
704
705 S.EmitRecord(pch::PP_TOKEN, Record);
706 Record.clear();
707 }
Chris Lattner7c5d24e2009-04-10 18:00:12 +0000708
709 }
710
Chris Lattnerf04ad692009-04-10 17:16:57 +0000711 S.ExitBlock();
Chris Lattner0b1fb982009-04-10 17:15:23 +0000712}
713
714
Douglas Gregor2cf26342009-04-09 22:27:44 +0000715/// \brief Write the representation of a type to the PCH stream.
716void PCHWriter::WriteType(const Type *T) {
Douglas Gregor8038d512009-04-10 17:25:41 +0000717 pch::TypeID &ID = TypeIDs[T];
Chris Lattnerf04ad692009-04-10 17:16:57 +0000718 if (ID == 0) // we haven't seen this type before.
Douglas Gregor2cf26342009-04-09 22:27:44 +0000719 ID = NextTypeID++;
720
721 // Record the offset for this type.
722 if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS)
723 TypeOffsets.push_back(S.GetCurrentBitNo());
724 else if (TypeOffsets.size() < ID - pch::NUM_PREDEF_TYPE_IDS) {
725 TypeOffsets.resize(ID + 1 - pch::NUM_PREDEF_TYPE_IDS);
726 TypeOffsets[ID - pch::NUM_PREDEF_TYPE_IDS] = S.GetCurrentBitNo();
727 }
728
729 RecordData Record;
730
731 // Emit the type's representation.
732 PCHTypeWriter W(*this, Record);
733 switch (T->getTypeClass()) {
734 // For all of the concrete, non-dependent types, call the
735 // appropriate visitor function.
736#define TYPE(Class, Base) \
737 case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
738#define ABSTRACT_TYPE(Class, Base)
739#define DEPENDENT_TYPE(Class, Base)
740#include "clang/AST/TypeNodes.def"
741
742 // For all of the dependent type nodes (which only occur in C++
743 // templates), produce an error.
744#define TYPE(Class, Base)
745#define DEPENDENT_TYPE(Class, Base) case Type::Class:
746#include "clang/AST/TypeNodes.def"
747 assert(false && "Cannot serialize dependent type nodes");
748 break;
749 }
750
751 // Emit the serialized record.
752 S.EmitRecord(W.Code, Record);
753}
754
755/// \brief Write a block containing all of the types.
756void PCHWriter::WriteTypesBlock(ASTContext &Context) {
Chris Lattnerf04ad692009-04-10 17:16:57 +0000757 // Enter the types block.
Douglas Gregor2cf26342009-04-09 22:27:44 +0000758 S.EnterSubblock(pch::TYPES_BLOCK_ID, 2);
759
760 // Emit all of the types in the ASTContext
761 for (std::vector<Type*>::const_iterator T = Context.getTypes().begin(),
762 TEnd = Context.getTypes().end();
763 T != TEnd; ++T) {
764 // Builtin types are never serialized.
765 if (isa<BuiltinType>(*T))
766 continue;
767
768 WriteType(*T);
769 }
770
771 // Exit the types block
772 S.ExitBlock();
Douglas Gregor2cf26342009-04-09 22:27:44 +0000773}
774
775/// \brief Write the block containing all of the declaration IDs
776/// lexically declared within the given DeclContext.
777///
778/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
779/// bistream, or 0 if no block was written.
780uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
781 DeclContext *DC) {
Douglas Gregor8038d512009-04-10 17:25:41 +0000782 if (DC->decls_empty(Context))
Douglas Gregor2cf26342009-04-09 22:27:44 +0000783 return 0;
784
785 uint64_t Offset = S.GetCurrentBitNo();
786 RecordData Record;
787 for (DeclContext::decl_iterator D = DC->decls_begin(Context),
788 DEnd = DC->decls_end(Context);
789 D != DEnd; ++D)
790 AddDeclRef(*D, Record);
791
792 S.EmitRecord(pch::DECL_CONTEXT_LEXICAL, Record);
793 return Offset;
794}
795
796/// \brief Write the block containing all of the declaration IDs
797/// visible from the given DeclContext.
798///
799/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
800/// bistream, or 0 if no block was written.
801uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
802 DeclContext *DC) {
803 if (DC->getPrimaryContext() != DC)
804 return 0;
805
806 // Force the DeclContext to build a its name-lookup table.
807 DC->lookup(Context, DeclarationName());
808
809 // Serialize the contents of the mapping used for lookup. Note that,
810 // although we have two very different code paths, the serialized
811 // representation is the same for both cases: a declaration name,
812 // followed by a size, followed by references to the visible
813 // declarations that have that name.
814 uint64_t Offset = S.GetCurrentBitNo();
815 RecordData Record;
816 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
Douglas Gregor8c700062009-04-13 21:20:57 +0000817 if (!Map)
818 return 0;
819
Douglas Gregor2cf26342009-04-09 22:27:44 +0000820 for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
821 D != DEnd; ++D) {
822 AddDeclarationName(D->first, Record);
823 DeclContext::lookup_result Result = D->second.getLookupResult(Context);
824 Record.push_back(Result.second - Result.first);
825 for(; Result.first != Result.second; ++Result.first)
826 AddDeclRef(*Result.first, Record);
827 }
828
829 if (Record.size() == 0)
830 return 0;
831
832 S.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record);
833 return Offset;
834}
835
836/// \brief Write a block containing all of the declarations.
837void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
Chris Lattnerf04ad692009-04-10 17:16:57 +0000838 // Enter the declarations block.
Douglas Gregor2cf26342009-04-09 22:27:44 +0000839 S.EnterSubblock(pch::DECLS_BLOCK_ID, 2);
840
841 // Emit all of the declarations.
842 RecordData Record;
843 PCHDeclWriter W(*this, Record);
844 while (!DeclsToEmit.empty()) {
845 // Pull the next declaration off the queue
846 Decl *D = DeclsToEmit.front();
847 DeclsToEmit.pop();
848
849 // If this declaration is also a DeclContext, write blocks for the
850 // declarations that lexically stored inside its context and those
851 // declarations that are visible from its context. These blocks
852 // are written before the declaration itself so that we can put
853 // their offsets into the record for the declaration.
854 uint64_t LexicalOffset = 0;
855 uint64_t VisibleOffset = 0;
856 DeclContext *DC = dyn_cast<DeclContext>(D);
857 if (DC) {
858 LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
859 VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
860 }
861
862 // Determine the ID for this declaration
Douglas Gregor8038d512009-04-10 17:25:41 +0000863 pch::DeclID ID = DeclIDs[D];
Douglas Gregor2cf26342009-04-09 22:27:44 +0000864 if (ID == 0)
865 ID = DeclIDs.size();
866
867 unsigned Index = ID - 1;
868
869 // Record the offset for this declaration
870 if (DeclOffsets.size() == Index)
871 DeclOffsets.push_back(S.GetCurrentBitNo());
872 else if (DeclOffsets.size() < Index) {
873 DeclOffsets.resize(Index+1);
874 DeclOffsets[Index] = S.GetCurrentBitNo();
875 }
876
877 // Build and emit a record for this declaration
878 Record.clear();
879 W.Code = (pch::DeclCode)0;
880 W.Visit(D);
881 if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
882 assert(W.Code && "Visitor did not set record code");
883 S.EmitRecord(W.Code, Record);
884 }
885
886 // Exit the declarations block
887 S.ExitBlock();
Douglas Gregor2cf26342009-04-09 22:27:44 +0000888}
889
Douglas Gregorafaf3082009-04-11 00:14:32 +0000890/// \brief Write the identifier table into the PCH file.
891///
892/// The identifier table consists of a blob containing string data
893/// (the actual identifiers themselves) and a separate "offsets" index
894/// that maps identifier IDs to locations within the blob.
895void PCHWriter::WriteIdentifierTable() {
896 using namespace llvm;
897
898 // Create and write out the blob that contains the identifier
899 // strings.
900 RecordData IdentOffsets;
901 IdentOffsets.resize(IdentifierIDs.size());
902 {
903 // Create the identifier string data.
904 std::vector<char> Data;
905 Data.push_back(0); // Data must not be empty.
906 for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator
907 ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
908 ID != IDEnd; ++ID) {
909 assert(ID->first && "NULL identifier in identifier table");
910
911 // Make sure we're starting on an odd byte. The PCH reader
912 // expects the low bit to be set on all of the offsets.
913 if ((Data.size() & 0x01) == 0)
914 Data.push_back((char)0);
915
916 IdentOffsets[ID->second - 1] = Data.size();
917 Data.insert(Data.end(),
918 ID->first->getName(),
919 ID->first->getName() + ID->first->getLength());
920 Data.push_back((char)0);
921 }
922
923 // Create a blob abbreviation
924 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
925 Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE));
926 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Triple name
927 unsigned IDTableAbbrev = S.EmitAbbrev(Abbrev);
928
929 // Write the identifier table
930 RecordData Record;
931 Record.push_back(pch::IDENTIFIER_TABLE);
932 S.EmitRecordWithBlob(IDTableAbbrev, Record, &Data.front(), Data.size());
933 }
934
935 // Write the offsets table for identifier IDs.
936 S.EmitRecord(pch::IDENTIFIER_OFFSET, IdentOffsets);
937}
938
Douglas Gregor2cf26342009-04-09 22:27:44 +0000939PCHWriter::PCHWriter(llvm::BitstreamWriter &S)
940 : S(S), NextTypeID(pch::NUM_PREDEF_TYPE_IDS) { }
941
Chris Lattnerdf961c22009-04-10 18:08:30 +0000942void PCHWriter::WritePCH(ASTContext &Context, const Preprocessor &PP) {
Douglas Gregor2cf26342009-04-09 22:27:44 +0000943 // Emit the file header.
944 S.Emit((unsigned)'C', 8);
945 S.Emit((unsigned)'P', 8);
946 S.Emit((unsigned)'C', 8);
947 S.Emit((unsigned)'H', 8);
948
949 // The translation unit is the first declaration we'll emit.
950 DeclIDs[Context.getTranslationUnitDecl()] = 1;
951 DeclsToEmit.push(Context.getTranslationUnitDecl());
952
953 // Write the remaining PCH contents.
Douglas Gregor2bec0412009-04-10 21:16:55 +0000954 S.EnterSubblock(pch::PCH_BLOCK_ID, 3);
955 WriteTargetTriple(Context.Target);
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000956 WriteLanguageOptions(Context.getLangOptions());
Douglas Gregor14f79002009-04-10 03:52:48 +0000957 WriteSourceManagerBlock(Context.getSourceManager());
Chris Lattner0b1fb982009-04-10 17:15:23 +0000958 WritePreprocessor(PP);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000959 WriteTypesBlock(Context);
960 WriteDeclsBlock(Context);
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000961 S.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
962 S.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
Douglas Gregorafaf3082009-04-11 00:14:32 +0000963 WriteIdentifierTable();
Douglas Gregor2cf26342009-04-09 22:27:44 +0000964 S.ExitBlock();
965}
966
967void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
968 Record.push_back(Loc.getRawEncoding());
969}
970
971void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
972 Record.push_back(Value.getBitWidth());
973 unsigned N = Value.getNumWords();
974 const uint64_t* Words = Value.getRawData();
975 for (unsigned I = 0; I != N; ++I)
976 Record.push_back(Words[I]);
977}
978
Douglas Gregor0a2b45e2009-04-13 18:14:40 +0000979void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) {
980 Record.push_back(Value.isUnsigned());
981 AddAPInt(Value, Record);
982}
983
Douglas Gregor2cf26342009-04-09 22:27:44 +0000984void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
Douglas Gregorafaf3082009-04-11 00:14:32 +0000985 if (II == 0) {
986 Record.push_back(0);
987 return;
988 }
989
990 pch::IdentID &ID = IdentifierIDs[II];
991 if (ID == 0)
992 ID = IdentifierIDs.size();
993
994 Record.push_back(ID);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000995}
996
997void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
998 if (T.isNull()) {
999 Record.push_back(pch::PREDEF_TYPE_NULL_ID);
1000 return;
1001 }
1002
1003 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
Douglas Gregore1d918e2009-04-10 23:10:45 +00001004 pch::TypeID ID = 0;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001005 switch (BT->getKind()) {
1006 case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break;
1007 case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break;
1008 case BuiltinType::Char_U: ID = pch::PREDEF_TYPE_CHAR_U_ID; break;
1009 case BuiltinType::UChar: ID = pch::PREDEF_TYPE_UCHAR_ID; break;
1010 case BuiltinType::UShort: ID = pch::PREDEF_TYPE_USHORT_ID; break;
1011 case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break;
1012 case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break;
1013 case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break;
1014 case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break;
1015 case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break;
1016 case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break;
1017 case BuiltinType::Short: ID = pch::PREDEF_TYPE_SHORT_ID; break;
1018 case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break;
1019 case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break;
1020 case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break;
1021 case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break;
1022 case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break;
1023 case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
1024 case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break;
1025 case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
1026 }
1027
1028 Record.push_back((ID << 3) | T.getCVRQualifiers());
1029 return;
1030 }
1031
Douglas Gregor8038d512009-04-10 17:25:41 +00001032 pch::TypeID &ID = TypeIDs[T.getTypePtr()];
Douglas Gregor2cf26342009-04-09 22:27:44 +00001033 if (ID == 0) // we haven't seen this type before
1034 ID = NextTypeID++;
1035
1036 // Encode the type qualifiers in the type reference.
1037 Record.push_back((ID << 3) | T.getCVRQualifiers());
1038}
1039
1040void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
1041 if (D == 0) {
1042 Record.push_back(0);
1043 return;
1044 }
1045
Douglas Gregor8038d512009-04-10 17:25:41 +00001046 pch::DeclID &ID = DeclIDs[D];
Douglas Gregor2cf26342009-04-09 22:27:44 +00001047 if (ID == 0) {
1048 // We haven't seen this declaration before. Give it a new ID and
1049 // enqueue it in the list of declarations to emit.
1050 ID = DeclIDs.size();
1051 DeclsToEmit.push(const_cast<Decl *>(D));
1052 }
1053
1054 Record.push_back(ID);
1055}
1056
1057void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
1058 Record.push_back(Name.getNameKind());
1059 switch (Name.getNameKind()) {
1060 case DeclarationName::Identifier:
1061 AddIdentifierRef(Name.getAsIdentifierInfo(), Record);
1062 break;
1063
1064 case DeclarationName::ObjCZeroArgSelector:
1065 case DeclarationName::ObjCOneArgSelector:
1066 case DeclarationName::ObjCMultiArgSelector:
1067 assert(false && "Serialization of Objective-C selectors unavailable");
1068 break;
1069
1070 case DeclarationName::CXXConstructorName:
1071 case DeclarationName::CXXDestructorName:
1072 case DeclarationName::CXXConversionFunctionName:
1073 AddTypeRef(Name.getCXXNameType(), Record);
1074 break;
1075
1076 case DeclarationName::CXXOperatorName:
1077 Record.push_back(Name.getCXXOverloadedOperator());
1078 break;
1079
1080 case DeclarationName::CXXUsingDirective:
1081 // No extra data to emit
1082 break;
1083 }
1084}