blob: 4b4e89716616d5c40baf852d03b03cc0dac9d916 [file] [log] [blame]
Douglas Gregorc34897d2009-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"
Douglas Gregorc10f86f2009-04-14 21:18:50 +000019#include "clang/AST/Expr.h"
20#include "clang/AST/StmtVisitor.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000021#include "clang/AST/Type.h"
Chris Lattner1b094952009-04-10 18:00:12 +000022#include "clang/Lex/MacroInfo.h"
23#include "clang/Lex/Preprocessor.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000024#include "clang/Basic/FileManager.h"
25#include "clang/Basic/SourceManager.h"
Douglas Gregor635f97f2009-04-13 16:31:14 +000026#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregorb5887f32009-04-10 21:16:55 +000027#include "clang/Basic/TargetInfo.h"
Douglas Gregore2f37202009-04-14 21:55:33 +000028#include "llvm/ADT/APFloat.h"
29#include "llvm/ADT/APInt.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000030#include "llvm/Bitcode/BitstreamWriter.h"
31#include "llvm/Support/Compiler.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000032#include "llvm/Support/MemoryBuffer.h"
Chris Lattner64b65f82009-04-11 18:40:46 +000033#include <cstdio>
Douglas Gregorc34897d2009-04-09 22:27:44 +000034using namespace clang;
35
36//===----------------------------------------------------------------------===//
37// Type serialization
38//===----------------------------------------------------------------------===//
39namespace {
40 class VISIBILITY_HIDDEN PCHTypeWriter {
41 PCHWriter &Writer;
42 PCHWriter::RecordData &Record;
43
44 public:
45 /// \brief Type code that corresponds to the record generated.
46 pch::TypeCode Code;
47
48 PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
49 : Writer(Writer), Record(Record) { }
50
51 void VisitArrayType(const ArrayType *T);
52 void VisitFunctionType(const FunctionType *T);
53 void VisitTagType(const TagType *T);
54
55#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
56#define ABSTRACT_TYPE(Class, Base)
57#define DEPENDENT_TYPE(Class, Base)
58#include "clang/AST/TypeNodes.def"
59 };
60}
61
62void PCHTypeWriter::VisitExtQualType(const ExtQualType *T) {
63 Writer.AddTypeRef(QualType(T->getBaseType(), 0), Record);
64 Record.push_back(T->getObjCGCAttr()); // FIXME: use stable values
65 Record.push_back(T->getAddressSpace());
66 Code = pch::TYPE_EXT_QUAL;
67}
68
69void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
70 assert(false && "Built-in types are never serialized");
71}
72
73void PCHTypeWriter::VisitFixedWidthIntType(const FixedWidthIntType *T) {
74 Record.push_back(T->getWidth());
75 Record.push_back(T->isSigned());
76 Code = pch::TYPE_FIXED_WIDTH_INT;
77}
78
79void PCHTypeWriter::VisitComplexType(const ComplexType *T) {
80 Writer.AddTypeRef(T->getElementType(), Record);
81 Code = pch::TYPE_COMPLEX;
82}
83
84void PCHTypeWriter::VisitPointerType(const PointerType *T) {
85 Writer.AddTypeRef(T->getPointeeType(), Record);
86 Code = pch::TYPE_POINTER;
87}
88
89void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
90 Writer.AddTypeRef(T->getPointeeType(), Record);
91 Code = pch::TYPE_BLOCK_POINTER;
92}
93
94void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
95 Writer.AddTypeRef(T->getPointeeType(), Record);
96 Code = pch::TYPE_LVALUE_REFERENCE;
97}
98
99void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
100 Writer.AddTypeRef(T->getPointeeType(), Record);
101 Code = pch::TYPE_RVALUE_REFERENCE;
102}
103
104void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
105 Writer.AddTypeRef(T->getPointeeType(), Record);
106 Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
107 Code = pch::TYPE_MEMBER_POINTER;
108}
109
110void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
111 Writer.AddTypeRef(T->getElementType(), Record);
112 Record.push_back(T->getSizeModifier()); // FIXME: stable values
113 Record.push_back(T->getIndexTypeQualifier()); // FIXME: stable values
114}
115
116void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
117 VisitArrayType(T);
118 Writer.AddAPInt(T->getSize(), Record);
119 Code = pch::TYPE_CONSTANT_ARRAY;
120}
121
122void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
123 VisitArrayType(T);
124 Code = pch::TYPE_INCOMPLETE_ARRAY;
125}
126
127void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
128 VisitArrayType(T);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000129 Writer.AddStmt(T->getSizeExpr());
Douglas Gregorc34897d2009-04-09 22:27:44 +0000130 Code = pch::TYPE_VARIABLE_ARRAY;
131}
132
133void PCHTypeWriter::VisitVectorType(const VectorType *T) {
134 Writer.AddTypeRef(T->getElementType(), Record);
135 Record.push_back(T->getNumElements());
136 Code = pch::TYPE_VECTOR;
137}
138
139void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
140 VisitVectorType(T);
141 Code = pch::TYPE_EXT_VECTOR;
142}
143
144void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
145 Writer.AddTypeRef(T->getResultType(), Record);
146}
147
148void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
149 VisitFunctionType(T);
150 Code = pch::TYPE_FUNCTION_NO_PROTO;
151}
152
153void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
154 VisitFunctionType(T);
155 Record.push_back(T->getNumArgs());
156 for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
157 Writer.AddTypeRef(T->getArgType(I), Record);
158 Record.push_back(T->isVariadic());
159 Record.push_back(T->getTypeQuals());
160 Code = pch::TYPE_FUNCTION_PROTO;
161}
162
163void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
164 Writer.AddDeclRef(T->getDecl(), Record);
165 Code = pch::TYPE_TYPEDEF;
166}
167
168void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000169 Writer.AddStmt(T->getUnderlyingExpr());
Douglas Gregorc34897d2009-04-09 22:27:44 +0000170 Code = pch::TYPE_TYPEOF_EXPR;
171}
172
173void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) {
174 Writer.AddTypeRef(T->getUnderlyingType(), Record);
175 Code = pch::TYPE_TYPEOF;
176}
177
178void PCHTypeWriter::VisitTagType(const TagType *T) {
179 Writer.AddDeclRef(T->getDecl(), Record);
180 assert(!T->isBeingDefined() &&
181 "Cannot serialize in the middle of a type definition");
182}
183
184void PCHTypeWriter::VisitRecordType(const RecordType *T) {
185 VisitTagType(T);
186 Code = pch::TYPE_RECORD;
187}
188
189void PCHTypeWriter::VisitEnumType(const EnumType *T) {
190 VisitTagType(T);
191 Code = pch::TYPE_ENUM;
192}
193
194void
195PCHTypeWriter::VisitTemplateSpecializationType(
196 const TemplateSpecializationType *T) {
Douglas Gregor3c8ff3e2009-04-15 18:43:11 +0000197 // FIXME: Serialize this type (C++ only)
Douglas Gregorc34897d2009-04-09 22:27:44 +0000198 assert(false && "Cannot serialize template specialization types");
199}
200
201void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) {
Douglas Gregor3c8ff3e2009-04-15 18:43:11 +0000202 // FIXME: Serialize this type (C++ only)
Douglas Gregorc34897d2009-04-09 22:27:44 +0000203 assert(false && "Cannot serialize qualified name types");
204}
205
206void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
207 Writer.AddDeclRef(T->getDecl(), Record);
208 Code = pch::TYPE_OBJC_INTERFACE;
209}
210
211void
212PCHTypeWriter::VisitObjCQualifiedInterfaceType(
213 const ObjCQualifiedInterfaceType *T) {
214 VisitObjCInterfaceType(T);
215 Record.push_back(T->getNumProtocols());
216 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
217 Writer.AddDeclRef(T->getProtocol(I), Record);
218 Code = pch::TYPE_OBJC_QUALIFIED_INTERFACE;
219}
220
221void PCHTypeWriter::VisitObjCQualifiedIdType(const ObjCQualifiedIdType *T) {
222 Record.push_back(T->getNumProtocols());
223 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
224 Writer.AddDeclRef(T->getProtocols(I), Record);
225 Code = pch::TYPE_OBJC_QUALIFIED_ID;
226}
227
228void
229PCHTypeWriter::VisitObjCQualifiedClassType(const ObjCQualifiedClassType *T) {
230 Record.push_back(T->getNumProtocols());
231 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
232 Writer.AddDeclRef(T->getProtocols(I), Record);
233 Code = pch::TYPE_OBJC_QUALIFIED_CLASS;
234}
235
236//===----------------------------------------------------------------------===//
237// Declaration serialization
238//===----------------------------------------------------------------------===//
239namespace {
240 class VISIBILITY_HIDDEN PCHDeclWriter
241 : public DeclVisitor<PCHDeclWriter, void> {
242
243 PCHWriter &Writer;
244 PCHWriter::RecordData &Record;
245
246 public:
247 pch::DeclCode Code;
248
249 PCHDeclWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
250 : Writer(Writer), Record(Record) { }
251
252 void VisitDecl(Decl *D);
253 void VisitTranslationUnitDecl(TranslationUnitDecl *D);
254 void VisitNamedDecl(NamedDecl *D);
255 void VisitTypeDecl(TypeDecl *D);
256 void VisitTypedefDecl(TypedefDecl *D);
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000257 void VisitTagDecl(TagDecl *D);
258 void VisitEnumDecl(EnumDecl *D);
Douglas Gregor982365e2009-04-13 21:20:57 +0000259 void VisitRecordDecl(RecordDecl *D);
Douglas Gregorc34897d2009-04-09 22:27:44 +0000260 void VisitValueDecl(ValueDecl *D);
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000261 void VisitEnumConstantDecl(EnumConstantDecl *D);
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000262 void VisitFunctionDecl(FunctionDecl *D);
Douglas Gregor982365e2009-04-13 21:20:57 +0000263 void VisitFieldDecl(FieldDecl *D);
Douglas Gregorc34897d2009-04-09 22:27:44 +0000264 void VisitVarDecl(VarDecl *D);
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000265 void VisitParmVarDecl(ParmVarDecl *D);
266 void VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
Douglas Gregor2a491792009-04-13 22:49:25 +0000267 void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
268 void VisitBlockDecl(BlockDecl *D);
Douglas Gregorc34897d2009-04-09 22:27:44 +0000269 void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
270 uint64_t VisibleOffset);
271 };
272}
273
274void PCHDeclWriter::VisitDecl(Decl *D) {
275 Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
276 Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
277 Writer.AddSourceLocation(D->getLocation(), Record);
278 Record.push_back(D->isInvalidDecl());
Douglas Gregor1c507882009-04-15 21:30:51 +0000279 Record.push_back(D->hasAttrs());
Douglas Gregorc34897d2009-04-09 22:27:44 +0000280 Record.push_back(D->isImplicit());
281 Record.push_back(D->getAccess());
282}
283
284void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
285 VisitDecl(D);
286 Code = pch::DECL_TRANSLATION_UNIT;
287}
288
289void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
290 VisitDecl(D);
291 Writer.AddDeclarationName(D->getDeclName(), Record);
292}
293
294void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
295 VisitNamedDecl(D);
296 Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
297}
298
299void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
300 VisitTypeDecl(D);
301 Writer.AddTypeRef(D->getUnderlyingType(), Record);
302 Code = pch::DECL_TYPEDEF;
303}
304
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000305void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
306 VisitTypeDecl(D);
307 Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
308 Record.push_back(D->isDefinition());
309 Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
310}
311
312void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
313 VisitTagDecl(D);
314 Writer.AddTypeRef(D->getIntegerType(), Record);
315 Code = pch::DECL_ENUM;
316}
317
Douglas Gregor982365e2009-04-13 21:20:57 +0000318void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
319 VisitTagDecl(D);
320 Record.push_back(D->hasFlexibleArrayMember());
321 Record.push_back(D->isAnonymousStructOrUnion());
322 Code = pch::DECL_RECORD;
323}
324
Douglas Gregorc34897d2009-04-09 22:27:44 +0000325void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
326 VisitNamedDecl(D);
327 Writer.AddTypeRef(D->getType(), Record);
328}
329
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000330void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
331 VisitValueDecl(D);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000332 Record.push_back(D->getInitExpr()? 1 : 0);
333 if (D->getInitExpr())
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000334 Writer.AddStmt(D->getInitExpr());
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000335 Writer.AddAPSInt(D->getInitVal(), Record);
336 Code = pch::DECL_ENUM_CONSTANT;
337}
338
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000339void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
340 VisitValueDecl(D);
Douglas Gregor9c4782a2009-04-17 00:04:06 +0000341 Record.push_back(D->isThisDeclarationADefinition());
342 if (D->isThisDeclarationADefinition())
343 Writer.AddStmt(D->getBody());
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000344 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
345 Record.push_back(D->getStorageClass()); // FIXME: stable encoding
346 Record.push_back(D->isInline());
347 Record.push_back(D->isVirtual());
348 Record.push_back(D->isPure());
349 Record.push_back(D->inheritedPrototype());
350 Record.push_back(D->hasPrototype() && !D->inheritedPrototype());
351 Record.push_back(D->isDeleted());
352 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
353 Record.push_back(D->param_size());
354 for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
355 P != PEnd; ++P)
356 Writer.AddDeclRef(*P, Record);
357 Code = pch::DECL_FUNCTION;
358}
359
Douglas Gregor982365e2009-04-13 21:20:57 +0000360void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
361 VisitValueDecl(D);
362 Record.push_back(D->isMutable());
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000363 Record.push_back(D->getBitWidth()? 1 : 0);
364 if (D->getBitWidth())
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000365 Writer.AddStmt(D->getBitWidth());
Douglas Gregor982365e2009-04-13 21:20:57 +0000366 Code = pch::DECL_FIELD;
367}
368
Douglas Gregorc34897d2009-04-09 22:27:44 +0000369void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
370 VisitValueDecl(D);
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000371 Record.push_back(D->getStorageClass()); // FIXME: stable encoding
Douglas Gregorc34897d2009-04-09 22:27:44 +0000372 Record.push_back(D->isThreadSpecified());
373 Record.push_back(D->hasCXXDirectInitializer());
374 Record.push_back(D->isDeclaredInCondition());
375 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
376 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000377 Record.push_back(D->getInit()? 1 : 0);
378 if (D->getInit())
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000379 Writer.AddStmt(D->getInit());
Douglas Gregorc34897d2009-04-09 22:27:44 +0000380 Code = pch::DECL_VAR;
381}
382
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000383void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
384 VisitVarDecl(D);
385 Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
Douglas Gregor3c8ff3e2009-04-15 18:43:11 +0000386 // FIXME: emit default argument (C++)
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000387 // FIXME: why isn't the "default argument" just stored as the initializer
388 // in VarDecl?
389 Code = pch::DECL_PARM_VAR;
390}
391
392void PCHDeclWriter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
393 VisitParmVarDecl(D);
394 Writer.AddTypeRef(D->getOriginalType(), Record);
395 Code = pch::DECL_ORIGINAL_PARM_VAR;
396}
397
Douglas Gregor2a491792009-04-13 22:49:25 +0000398void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
399 VisitDecl(D);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000400 Writer.AddStmt(D->getAsmString());
Douglas Gregor2a491792009-04-13 22:49:25 +0000401 Code = pch::DECL_FILE_SCOPE_ASM;
402}
403
404void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
405 VisitDecl(D);
406 // FIXME: emit block body
407 Record.push_back(D->param_size());
408 for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
409 P != PEnd; ++P)
410 Writer.AddDeclRef(*P, Record);
411 Code = pch::DECL_BLOCK;
412}
413
Douglas Gregorc34897d2009-04-09 22:27:44 +0000414/// \brief Emit the DeclContext part of a declaration context decl.
415///
416/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
417/// block for this declaration context is stored. May be 0 to indicate
418/// that there are no declarations stored within this context.
419///
420/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
421/// block for this declaration context is stored. May be 0 to indicate
422/// that there are no declarations visible from this context. Note
423/// that this value will not be emitted for non-primary declaration
424/// contexts.
425void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
426 uint64_t VisibleOffset) {
427 Record.push_back(LexicalOffset);
428 if (DC->getPrimaryContext() == DC)
429 Record.push_back(VisibleOffset);
430}
431
432//===----------------------------------------------------------------------===//
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000433// Statement/expression serialization
434//===----------------------------------------------------------------------===//
435namespace {
436 class VISIBILITY_HIDDEN PCHStmtWriter
437 : public StmtVisitor<PCHStmtWriter, void> {
438
439 PCHWriter &Writer;
440 PCHWriter::RecordData &Record;
441
442 public:
443 pch::StmtCode Code;
444
445 PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
446 : Writer(Writer), Record(Record) { }
447
Douglas Gregor9c4782a2009-04-17 00:04:06 +0000448 void VisitStmt(Stmt *S);
449 void VisitNullStmt(NullStmt *S);
450 void VisitCompoundStmt(CompoundStmt *S);
451 void VisitSwitchCase(SwitchCase *S);
452 void VisitCaseStmt(CaseStmt *S);
453 void VisitDefaultStmt(DefaultStmt *S);
454 void VisitIfStmt(IfStmt *S);
455 void VisitSwitchStmt(SwitchStmt *S);
Douglas Gregora6b503f2009-04-17 00:16:09 +0000456 void VisitWhileStmt(WhileStmt *S);
Douglas Gregorfb5f25b2009-04-17 00:29:51 +0000457 void VisitDoStmt(DoStmt *S);
458 void VisitForStmt(ForStmt *S);
Douglas Gregora6b503f2009-04-17 00:16:09 +0000459 void VisitContinueStmt(ContinueStmt *S);
Douglas Gregor9c4782a2009-04-17 00:04:06 +0000460 void VisitBreakStmt(BreakStmt *S);
Douglas Gregor22d2dcd2009-04-17 16:34:57 +0000461 void VisitReturnStmt(ReturnStmt *S);
Douglas Gregor78ff29f2009-04-17 16:55:36 +0000462 void VisitDeclStmt(DeclStmt *S);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000463 void VisitExpr(Expr *E);
Douglas Gregore2f37202009-04-14 21:55:33 +0000464 void VisitPredefinedExpr(PredefinedExpr *E);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000465 void VisitDeclRefExpr(DeclRefExpr *E);
466 void VisitIntegerLiteral(IntegerLiteral *E);
Douglas Gregore2f37202009-04-14 21:55:33 +0000467 void VisitFloatingLiteral(FloatingLiteral *E);
Douglas Gregor21ddd8c2009-04-15 22:19:53 +0000468 void VisitImaginaryLiteral(ImaginaryLiteral *E);
Douglas Gregor596e0932009-04-15 16:35:07 +0000469 void VisitStringLiteral(StringLiteral *E);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000470 void VisitCharacterLiteral(CharacterLiteral *E);
Douglas Gregor4ea0b1f2009-04-14 23:59:37 +0000471 void VisitParenExpr(ParenExpr *E);
Douglas Gregor12d74052009-04-15 15:58:59 +0000472 void VisitUnaryOperator(UnaryOperator *E);
473 void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
Douglas Gregor21ddd8c2009-04-15 22:19:53 +0000474 void VisitArraySubscriptExpr(ArraySubscriptExpr *E);
Douglas Gregor7e2b1cd2009-04-15 17:43:59 +0000475 void VisitCallExpr(CallExpr *E);
476 void VisitMemberExpr(MemberExpr *E);
Douglas Gregora151ba42009-04-14 23:32:43 +0000477 void VisitCastExpr(CastExpr *E);
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000478 void VisitBinaryOperator(BinaryOperator *E);
Douglas Gregorc599bbf2009-04-15 22:40:36 +0000479 void VisitCompoundAssignOperator(CompoundAssignOperator *E);
480 void VisitConditionalOperator(ConditionalOperator *E);
Douglas Gregora151ba42009-04-14 23:32:43 +0000481 void VisitImplicitCastExpr(ImplicitCastExpr *E);
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000482 void VisitExplicitCastExpr(ExplicitCastExpr *E);
483 void VisitCStyleCastExpr(CStyleCastExpr *E);
Douglas Gregorb70b48f2009-04-16 02:33:48 +0000484 void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
Douglas Gregorec0b8292009-04-15 23:02:49 +0000485 void VisitExtVectorElementExpr(ExtVectorElementExpr *E);
Douglas Gregor6710a3c2009-04-16 00:55:48 +0000486 void VisitInitListExpr(InitListExpr *E);
487 void VisitDesignatedInitExpr(DesignatedInitExpr *E);
488 void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
Douglas Gregorec0b8292009-04-15 23:02:49 +0000489 void VisitVAArgExpr(VAArgExpr *E);
Douglas Gregor209d4622009-04-15 23:33:31 +0000490 void VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
491 void VisitChooseExpr(ChooseExpr *E);
492 void VisitGNUNullExpr(GNUNullExpr *E);
Douglas Gregor725e94b2009-04-16 00:01:45 +0000493 void VisitShuffleVectorExpr(ShuffleVectorExpr *E);
494 void VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000495 };
496}
497
Douglas Gregor9c4782a2009-04-17 00:04:06 +0000498void PCHStmtWriter::VisitStmt(Stmt *S) {
499}
500
501void PCHStmtWriter::VisitNullStmt(NullStmt *S) {
502 VisitStmt(S);
503 Writer.AddSourceLocation(S->getSemiLoc(), Record);
504 Code = pch::STMT_NULL;
505}
506
507void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
508 VisitStmt(S);
509 Record.push_back(S->size());
510 for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end();
511 CS != CSEnd; ++CS)
512 Writer.WriteSubStmt(*CS);
513 Writer.AddSourceLocation(S->getLBracLoc(), Record);
514 Writer.AddSourceLocation(S->getRBracLoc(), Record);
515 Code = pch::STMT_COMPOUND;
516}
517
518void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) {
519 VisitStmt(S);
520 Record.push_back(Writer.RecordSwitchCaseID(S));
521}
522
523void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) {
524 VisitSwitchCase(S);
525 Writer.WriteSubStmt(S->getLHS());
526 Writer.WriteSubStmt(S->getRHS());
527 Writer.WriteSubStmt(S->getSubStmt());
528 Writer.AddSourceLocation(S->getCaseLoc(), Record);
529 Code = pch::STMT_CASE;
530}
531
532void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
533 VisitSwitchCase(S);
534 Writer.WriteSubStmt(S->getSubStmt());
535 Writer.AddSourceLocation(S->getDefaultLoc(), Record);
536 Code = pch::STMT_DEFAULT;
537}
538
539void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
540 VisitStmt(S);
541 Writer.WriteSubStmt(S->getCond());
542 Writer.WriteSubStmt(S->getThen());
543 Writer.WriteSubStmt(S->getElse());
544 Writer.AddSourceLocation(S->getIfLoc(), Record);
545 Code = pch::STMT_IF;
546}
547
548void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
549 VisitStmt(S);
550 Writer.WriteSubStmt(S->getCond());
551 Writer.WriteSubStmt(S->getBody());
552 Writer.AddSourceLocation(S->getSwitchLoc(), Record);
553 for (SwitchCase *SC = S->getSwitchCaseList(); SC;
554 SC = SC->getNextSwitchCase())
555 Record.push_back(Writer.getSwitchCaseID(SC));
556 Code = pch::STMT_SWITCH;
557}
558
Douglas Gregora6b503f2009-04-17 00:16:09 +0000559void PCHStmtWriter::VisitWhileStmt(WhileStmt *S) {
560 VisitStmt(S);
561 Writer.WriteSubStmt(S->getCond());
562 Writer.WriteSubStmt(S->getBody());
563 Writer.AddSourceLocation(S->getWhileLoc(), Record);
564 Code = pch::STMT_WHILE;
565}
566
Douglas Gregorfb5f25b2009-04-17 00:29:51 +0000567void PCHStmtWriter::VisitDoStmt(DoStmt *S) {
568 VisitStmt(S);
569 Writer.WriteSubStmt(S->getCond());
570 Writer.WriteSubStmt(S->getBody());
571 Writer.AddSourceLocation(S->getDoLoc(), Record);
572 Code = pch::STMT_DO;
573}
574
575void PCHStmtWriter::VisitForStmt(ForStmt *S) {
576 VisitStmt(S);
577 Writer.WriteSubStmt(S->getInit());
578 Writer.WriteSubStmt(S->getCond());
579 Writer.WriteSubStmt(S->getInc());
580 Writer.WriteSubStmt(S->getBody());
581 Writer.AddSourceLocation(S->getForLoc(), Record);
582 Code = pch::STMT_FOR;
583}
584
Douglas Gregora6b503f2009-04-17 00:16:09 +0000585void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) {
586 VisitStmt(S);
587 Writer.AddSourceLocation(S->getContinueLoc(), Record);
588 Code = pch::STMT_CONTINUE;
589}
590
Douglas Gregor9c4782a2009-04-17 00:04:06 +0000591void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) {
592 VisitStmt(S);
593 Writer.AddSourceLocation(S->getBreakLoc(), Record);
594 Code = pch::STMT_BREAK;
595}
596
Douglas Gregor22d2dcd2009-04-17 16:34:57 +0000597void PCHStmtWriter::VisitReturnStmt(ReturnStmt *S) {
598 VisitStmt(S);
599 Writer.WriteSubStmt(S->getRetValue());
600 Writer.AddSourceLocation(S->getReturnLoc(), Record);
601 Code = pch::STMT_RETURN;
602}
603
Douglas Gregor78ff29f2009-04-17 16:55:36 +0000604void PCHStmtWriter::VisitDeclStmt(DeclStmt *S) {
605 VisitStmt(S);
606 Writer.AddSourceLocation(S->getStartLoc(), Record);
607 Writer.AddSourceLocation(S->getEndLoc(), Record);
608 DeclGroupRef DG = S->getDeclGroup();
609 for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D)
610 Writer.AddDeclRef(*D, Record);
611 Code = pch::STMT_DECL;
612}
613
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000614void PCHStmtWriter::VisitExpr(Expr *E) {
Douglas Gregor9c4782a2009-04-17 00:04:06 +0000615 VisitStmt(E);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000616 Writer.AddTypeRef(E->getType(), Record);
617 Record.push_back(E->isTypeDependent());
618 Record.push_back(E->isValueDependent());
619}
620
Douglas Gregore2f37202009-04-14 21:55:33 +0000621void PCHStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
622 VisitExpr(E);
623 Writer.AddSourceLocation(E->getLocation(), Record);
624 Record.push_back(E->getIdentType()); // FIXME: stable encoding
625 Code = pch::EXPR_PREDEFINED;
626}
627
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000628void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
629 VisitExpr(E);
630 Writer.AddDeclRef(E->getDecl(), Record);
631 Writer.AddSourceLocation(E->getLocation(), Record);
632 Code = pch::EXPR_DECL_REF;
633}
634
635void PCHStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
636 VisitExpr(E);
637 Writer.AddSourceLocation(E->getLocation(), Record);
638 Writer.AddAPInt(E->getValue(), Record);
639 Code = pch::EXPR_INTEGER_LITERAL;
640}
641
Douglas Gregore2f37202009-04-14 21:55:33 +0000642void PCHStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
643 VisitExpr(E);
644 Writer.AddAPFloat(E->getValue(), Record);
645 Record.push_back(E->isExact());
646 Writer.AddSourceLocation(E->getLocation(), Record);
647 Code = pch::EXPR_FLOATING_LITERAL;
648}
649
Douglas Gregor21ddd8c2009-04-15 22:19:53 +0000650void PCHStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
651 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000652 Writer.WriteSubStmt(E->getSubExpr());
Douglas Gregor21ddd8c2009-04-15 22:19:53 +0000653 Code = pch::EXPR_IMAGINARY_LITERAL;
654}
655
Douglas Gregor596e0932009-04-15 16:35:07 +0000656void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) {
657 VisitExpr(E);
658 Record.push_back(E->getByteLength());
659 Record.push_back(E->getNumConcatenated());
660 Record.push_back(E->isWide());
661 // FIXME: String data should be stored as a blob at the end of the
662 // StringLiteral. However, we can't do so now because we have no
663 // provision for coping with abbreviations when we're jumping around
664 // the PCH file during deserialization.
665 Record.insert(Record.end(),
666 E->getStrData(), E->getStrData() + E->getByteLength());
667 for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
668 Writer.AddSourceLocation(E->getStrTokenLoc(I), Record);
669 Code = pch::EXPR_STRING_LITERAL;
670}
671
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000672void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) {
673 VisitExpr(E);
674 Record.push_back(E->getValue());
675 Writer.AddSourceLocation(E->getLoc(), Record);
676 Record.push_back(E->isWide());
677 Code = pch::EXPR_CHARACTER_LITERAL;
678}
679
Douglas Gregor4ea0b1f2009-04-14 23:59:37 +0000680void PCHStmtWriter::VisitParenExpr(ParenExpr *E) {
681 VisitExpr(E);
682 Writer.AddSourceLocation(E->getLParen(), Record);
683 Writer.AddSourceLocation(E->getRParen(), Record);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000684 Writer.WriteSubStmt(E->getSubExpr());
Douglas Gregor4ea0b1f2009-04-14 23:59:37 +0000685 Code = pch::EXPR_PAREN;
686}
687
Douglas Gregor12d74052009-04-15 15:58:59 +0000688void PCHStmtWriter::VisitUnaryOperator(UnaryOperator *E) {
689 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000690 Writer.WriteSubStmt(E->getSubExpr());
Douglas Gregor12d74052009-04-15 15:58:59 +0000691 Record.push_back(E->getOpcode()); // FIXME: stable encoding
692 Writer.AddSourceLocation(E->getOperatorLoc(), Record);
693 Code = pch::EXPR_UNARY_OPERATOR;
694}
695
696void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
697 VisitExpr(E);
698 Record.push_back(E->isSizeOf());
699 if (E->isArgumentType())
700 Writer.AddTypeRef(E->getArgumentType(), Record);
701 else {
702 Record.push_back(0);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000703 Writer.WriteSubStmt(E->getArgumentExpr());
Douglas Gregor12d74052009-04-15 15:58:59 +0000704 }
705 Writer.AddSourceLocation(E->getOperatorLoc(), Record);
706 Writer.AddSourceLocation(E->getRParenLoc(), Record);
707 Code = pch::EXPR_SIZEOF_ALIGN_OF;
708}
709
Douglas Gregor21ddd8c2009-04-15 22:19:53 +0000710void PCHStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
711 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000712 Writer.WriteSubStmt(E->getLHS());
713 Writer.WriteSubStmt(E->getRHS());
Douglas Gregor21ddd8c2009-04-15 22:19:53 +0000714 Writer.AddSourceLocation(E->getRBracketLoc(), Record);
715 Code = pch::EXPR_ARRAY_SUBSCRIPT;
716}
717
Douglas Gregor7e2b1cd2009-04-15 17:43:59 +0000718void PCHStmtWriter::VisitCallExpr(CallExpr *E) {
719 VisitExpr(E);
720 Record.push_back(E->getNumArgs());
721 Writer.AddSourceLocation(E->getRParenLoc(), Record);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000722 Writer.WriteSubStmt(E->getCallee());
Douglas Gregor7e2b1cd2009-04-15 17:43:59 +0000723 for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
724 Arg != ArgEnd; ++Arg)
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000725 Writer.WriteSubStmt(*Arg);
Douglas Gregor7e2b1cd2009-04-15 17:43:59 +0000726 Code = pch::EXPR_CALL;
727}
728
729void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) {
730 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000731 Writer.WriteSubStmt(E->getBase());
Douglas Gregor7e2b1cd2009-04-15 17:43:59 +0000732 Writer.AddDeclRef(E->getMemberDecl(), Record);
733 Writer.AddSourceLocation(E->getMemberLoc(), Record);
734 Record.push_back(E->isArrow());
735 Code = pch::EXPR_MEMBER;
736}
737
Douglas Gregora151ba42009-04-14 23:32:43 +0000738void PCHStmtWriter::VisitCastExpr(CastExpr *E) {
739 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000740 Writer.WriteSubStmt(E->getSubExpr());
Douglas Gregora151ba42009-04-14 23:32:43 +0000741}
742
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000743void PCHStmtWriter::VisitBinaryOperator(BinaryOperator *E) {
744 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000745 Writer.WriteSubStmt(E->getLHS());
746 Writer.WriteSubStmt(E->getRHS());
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000747 Record.push_back(E->getOpcode()); // FIXME: stable encoding
748 Writer.AddSourceLocation(E->getOperatorLoc(), Record);
749 Code = pch::EXPR_BINARY_OPERATOR;
750}
751
Douglas Gregorc599bbf2009-04-15 22:40:36 +0000752void PCHStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
753 VisitBinaryOperator(E);
754 Writer.AddTypeRef(E->getComputationLHSType(), Record);
755 Writer.AddTypeRef(E->getComputationResultType(), Record);
756 Code = pch::EXPR_COMPOUND_ASSIGN_OPERATOR;
757}
758
759void PCHStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
760 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000761 Writer.WriteSubStmt(E->getCond());
762 Writer.WriteSubStmt(E->getLHS());
763 Writer.WriteSubStmt(E->getRHS());
Douglas Gregorc599bbf2009-04-15 22:40:36 +0000764 Code = pch::EXPR_CONDITIONAL_OPERATOR;
765}
766
Douglas Gregora151ba42009-04-14 23:32:43 +0000767void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
768 VisitCastExpr(E);
769 Record.push_back(E->isLvalueCast());
770 Code = pch::EXPR_IMPLICIT_CAST;
771}
772
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000773void PCHStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
774 VisitCastExpr(E);
775 Writer.AddTypeRef(E->getTypeAsWritten(), Record);
776}
777
778void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
779 VisitExplicitCastExpr(E);
780 Writer.AddSourceLocation(E->getLParenLoc(), Record);
781 Writer.AddSourceLocation(E->getRParenLoc(), Record);
782 Code = pch::EXPR_CSTYLE_CAST;
783}
784
Douglas Gregorb70b48f2009-04-16 02:33:48 +0000785void PCHStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
786 VisitExpr(E);
787 Writer.AddSourceLocation(E->getLParenLoc(), Record);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000788 Writer.WriteSubStmt(E->getInitializer());
Douglas Gregorb70b48f2009-04-16 02:33:48 +0000789 Record.push_back(E->isFileScope());
790 Code = pch::EXPR_COMPOUND_LITERAL;
791}
792
Douglas Gregorec0b8292009-04-15 23:02:49 +0000793void PCHStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
794 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000795 Writer.WriteSubStmt(E->getBase());
Douglas Gregorec0b8292009-04-15 23:02:49 +0000796 Writer.AddIdentifierRef(&E->getAccessor(), Record);
797 Writer.AddSourceLocation(E->getAccessorLoc(), Record);
798 Code = pch::EXPR_EXT_VECTOR_ELEMENT;
799}
800
Douglas Gregor6710a3c2009-04-16 00:55:48 +0000801void PCHStmtWriter::VisitInitListExpr(InitListExpr *E) {
802 VisitExpr(E);
803 Record.push_back(E->getNumInits());
804 for (unsigned I = 0, N = E->getNumInits(); I != N; ++I)
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000805 Writer.WriteSubStmt(E->getInit(I));
806 Writer.WriteSubStmt(E->getSyntacticForm());
Douglas Gregor6710a3c2009-04-16 00:55:48 +0000807 Writer.AddSourceLocation(E->getLBraceLoc(), Record);
808 Writer.AddSourceLocation(E->getRBraceLoc(), Record);
809 Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record);
810 Record.push_back(E->hadArrayRangeDesignator());
811 Code = pch::EXPR_INIT_LIST;
812}
813
814void PCHStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
815 VisitExpr(E);
816 Record.push_back(E->getNumSubExprs());
817 for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000818 Writer.WriteSubStmt(E->getSubExpr(I));
Douglas Gregor6710a3c2009-04-16 00:55:48 +0000819 Writer.AddSourceLocation(E->getEqualOrColonLoc(), Record);
820 Record.push_back(E->usesGNUSyntax());
821 for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
822 DEnd = E->designators_end();
823 D != DEnd; ++D) {
824 if (D->isFieldDesignator()) {
825 if (FieldDecl *Field = D->getField()) {
826 Record.push_back(pch::DESIG_FIELD_DECL);
827 Writer.AddDeclRef(Field, Record);
828 } else {
829 Record.push_back(pch::DESIG_FIELD_NAME);
830 Writer.AddIdentifierRef(D->getFieldName(), Record);
831 }
832 Writer.AddSourceLocation(D->getDotLoc(), Record);
833 Writer.AddSourceLocation(D->getFieldLoc(), Record);
834 } else if (D->isArrayDesignator()) {
835 Record.push_back(pch::DESIG_ARRAY);
836 Record.push_back(D->getFirstExprIndex());
837 Writer.AddSourceLocation(D->getLBracketLoc(), Record);
838 Writer.AddSourceLocation(D->getRBracketLoc(), Record);
839 } else {
840 assert(D->isArrayRangeDesignator() && "Unknown designator");
841 Record.push_back(pch::DESIG_ARRAY_RANGE);
842 Record.push_back(D->getFirstExprIndex());
843 Writer.AddSourceLocation(D->getLBracketLoc(), Record);
844 Writer.AddSourceLocation(D->getEllipsisLoc(), Record);
845 Writer.AddSourceLocation(D->getRBracketLoc(), Record);
846 }
847 }
848 Code = pch::EXPR_DESIGNATED_INIT;
849}
850
851void PCHStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
852 VisitExpr(E);
853 Code = pch::EXPR_IMPLICIT_VALUE_INIT;
854}
855
Douglas Gregorec0b8292009-04-15 23:02:49 +0000856void PCHStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
857 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000858 Writer.WriteSubStmt(E->getSubExpr());
Douglas Gregorec0b8292009-04-15 23:02:49 +0000859 Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
860 Writer.AddSourceLocation(E->getRParenLoc(), Record);
861 Code = pch::EXPR_VA_ARG;
862}
863
Douglas Gregor209d4622009-04-15 23:33:31 +0000864void PCHStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
865 VisitExpr(E);
866 Writer.AddTypeRef(E->getArgType1(), Record);
867 Writer.AddTypeRef(E->getArgType2(), Record);
868 Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
869 Writer.AddSourceLocation(E->getRParenLoc(), Record);
870 Code = pch::EXPR_TYPES_COMPATIBLE;
871}
872
873void PCHStmtWriter::VisitChooseExpr(ChooseExpr *E) {
874 VisitExpr(E);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000875 Writer.WriteSubStmt(E->getCond());
876 Writer.WriteSubStmt(E->getLHS());
877 Writer.WriteSubStmt(E->getRHS());
Douglas Gregor209d4622009-04-15 23:33:31 +0000878 Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
879 Writer.AddSourceLocation(E->getRParenLoc(), Record);
880 Code = pch::EXPR_CHOOSE;
881}
882
883void PCHStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) {
884 VisitExpr(E);
885 Writer.AddSourceLocation(E->getTokenLocation(), Record);
886 Code = pch::EXPR_GNU_NULL;
887}
888
Douglas Gregor725e94b2009-04-16 00:01:45 +0000889void PCHStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
890 VisitExpr(E);
891 Record.push_back(E->getNumSubExprs());
892 for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000893 Writer.WriteSubStmt(E->getExpr(I));
Douglas Gregor725e94b2009-04-16 00:01:45 +0000894 Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
895 Writer.AddSourceLocation(E->getRParenLoc(), Record);
896 Code = pch::EXPR_SHUFFLE_VECTOR;
897}
898
899void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
900 VisitExpr(E);
901 Writer.AddDeclRef(E->getDecl(), Record);
902 Writer.AddSourceLocation(E->getLocation(), Record);
903 Record.push_back(E->isByRef());
904 Code = pch::EXPR_BLOCK_DECL_REF;
905}
906
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000907//===----------------------------------------------------------------------===//
Douglas Gregorc34897d2009-04-09 22:27:44 +0000908// PCHWriter Implementation
909//===----------------------------------------------------------------------===//
910
Douglas Gregorb5887f32009-04-10 21:16:55 +0000911/// \brief Write the target triple (e.g., i686-apple-darwin9).
912void PCHWriter::WriteTargetTriple(const TargetInfo &Target) {
913 using namespace llvm;
914 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
915 Abbrev->Add(BitCodeAbbrevOp(pch::TARGET_TRIPLE));
916 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Triple name
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000917 unsigned TripleAbbrev = Stream.EmitAbbrev(Abbrev);
Douglas Gregorb5887f32009-04-10 21:16:55 +0000918
919 RecordData Record;
920 Record.push_back(pch::TARGET_TRIPLE);
921 const char *Triple = Target.getTargetTriple();
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000922 Stream.EmitRecordWithBlob(TripleAbbrev, Record, Triple, strlen(Triple));
Douglas Gregorb5887f32009-04-10 21:16:55 +0000923}
924
925/// \brief Write the LangOptions structure.
Douglas Gregor179cfb12009-04-10 20:39:37 +0000926void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
927 RecordData Record;
928 Record.push_back(LangOpts.Trigraphs);
929 Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments.
930 Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers.
931 Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode.
932 Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc)
933 Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'.
934 Record.push_back(LangOpts.Digraphs); // C94, C99 and C++
935 Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants.
936 Record.push_back(LangOpts.C99); // C99 Support
937 Record.push_back(LangOpts.Microsoft); // Microsoft extensions.
938 Record.push_back(LangOpts.CPlusPlus); // C++ Support
939 Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support
940 Record.push_back(LangOpts.NoExtensions); // All extensions are disabled, strict mode.
941 Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords.
942
943 Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled.
944 Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled.
945 Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C modern abi enabled
946
947 Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings
948 Record.push_back(LangOpts.Boolean); // Allow bool/true/false
949 Record.push_back(LangOpts.WritableStrings); // Allow writable strings
950 Record.push_back(LangOpts.LaxVectorConversions);
951 Record.push_back(LangOpts.Exceptions); // Support exception handling.
952
953 Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime.
954 Record.push_back(LangOpts.Freestanding); // Freestanding implementation
955 Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin)
956
957 Record.push_back(LangOpts.ThreadsafeStatics); // Whether static initializers are protected
958 // by locks.
959 Record.push_back(LangOpts.Blocks); // block extension to C
960 Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if
961 // they are unused.
962 Record.push_back(LangOpts.MathErrno); // Math functions must respect errno
963 // (modulo the platform support).
964
965 Record.push_back(LangOpts.OverflowChecking); // Extension to call a handler function when
966 // signed integer arithmetic overflows.
967
968 Record.push_back(LangOpts.HeinousExtensions); // Extensions that we really don't like and
969 // may be ripped out at any time.
970
971 Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined.
972 Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be
973 // defined.
974 Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as
975 // opposed to __DYNAMIC__).
976 Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero.
977
978 Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be
979 // used (instead of C99 semantics).
980 Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined.
981 Record.push_back(LangOpts.getGCMode());
982 Record.push_back(LangOpts.getVisibilityMode());
983 Record.push_back(LangOpts.InstantiationDepth);
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000984 Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record);
Douglas Gregor179cfb12009-04-10 20:39:37 +0000985}
986
Douglas Gregorab1cef72009-04-10 03:52:48 +0000987//===----------------------------------------------------------------------===//
988// Source Manager Serialization
989//===----------------------------------------------------------------------===//
990
991/// \brief Create an abbreviation for the SLocEntry that refers to a
992/// file.
Douglas Gregorc72f6c82009-04-16 22:23:12 +0000993static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
Douglas Gregorab1cef72009-04-10 03:52:48 +0000994 using namespace llvm;
995 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
996 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
997 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
998 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
999 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
1000 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
Douglas Gregorab1cef72009-04-10 03:52:48 +00001001 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001002 return Stream.EmitAbbrev(Abbrev);
Douglas Gregorab1cef72009-04-10 03:52:48 +00001003}
1004
1005/// \brief Create an abbreviation for the SLocEntry that refers to a
1006/// buffer.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001007static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
Douglas Gregorab1cef72009-04-10 03:52:48 +00001008 using namespace llvm;
1009 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
1010 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
1011 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
1012 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
1013 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
1014 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
1015 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001016 return Stream.EmitAbbrev(Abbrev);
Douglas Gregorab1cef72009-04-10 03:52:48 +00001017}
1018
1019/// \brief Create an abbreviation for the SLocEntry that refers to a
1020/// buffer's blob.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001021static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
Douglas Gregorab1cef72009-04-10 03:52:48 +00001022 using namespace llvm;
1023 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
1024 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
1025 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001026 return Stream.EmitAbbrev(Abbrev);
Douglas Gregorab1cef72009-04-10 03:52:48 +00001027}
1028
1029/// \brief Create an abbreviation for the SLocEntry that refers to an
1030/// buffer.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001031static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) {
Douglas Gregorab1cef72009-04-10 03:52:48 +00001032 using namespace llvm;
1033 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
1034 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
1035 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
1036 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
1037 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
1038 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
Douglas Gregor364e5802009-04-15 18:05:10 +00001039 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001040 return Stream.EmitAbbrev(Abbrev);
Douglas Gregorab1cef72009-04-10 03:52:48 +00001041}
1042
1043/// \brief Writes the block containing the serialized form of the
1044/// source manager.
1045///
1046/// TODO: We should probably use an on-disk hash table (stored in a
1047/// blob), indexed based on the file name, so that we only create
1048/// entries for files that we actually need. In the common case (no
1049/// errors), we probably won't have to create file entries for any of
1050/// the files in the AST.
1051void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) {
Chris Lattner84b04f12009-04-10 17:16:57 +00001052 // Enter the source manager block.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001053 Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
Douglas Gregorab1cef72009-04-10 03:52:48 +00001054
1055 // Abbreviations for the various kinds of source-location entries.
1056 int SLocFileAbbrv = -1;
1057 int SLocBufferAbbrv = -1;
1058 int SLocBufferBlobAbbrv = -1;
1059 int SLocInstantiationAbbrv = -1;
1060
1061 // Write out the source location entry table. We skip the first
1062 // entry, which is always the same dummy entry.
1063 RecordData Record;
1064 for (SourceManager::sloc_entry_iterator
1065 SLoc = SourceMgr.sloc_entry_begin() + 1,
1066 SLocEnd = SourceMgr.sloc_entry_end();
1067 SLoc != SLocEnd; ++SLoc) {
1068 // Figure out which record code to use.
1069 unsigned Code;
1070 if (SLoc->isFile()) {
1071 if (SLoc->getFile().getContentCache()->Entry)
1072 Code = pch::SM_SLOC_FILE_ENTRY;
1073 else
1074 Code = pch::SM_SLOC_BUFFER_ENTRY;
1075 } else
1076 Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
1077 Record.push_back(Code);
1078
1079 Record.push_back(SLoc->getOffset());
1080 if (SLoc->isFile()) {
1081 const SrcMgr::FileInfo &File = SLoc->getFile();
1082 Record.push_back(File.getIncludeLoc().getRawEncoding());
1083 Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
Douglas Gregor635f97f2009-04-13 16:31:14 +00001084 Record.push_back(File.hasLineDirectives());
Douglas Gregorab1cef72009-04-10 03:52:48 +00001085
1086 const SrcMgr::ContentCache *Content = File.getContentCache();
1087 if (Content->Entry) {
1088 // The source location entry is a file. The blob associated
1089 // with this entry is the file name.
1090 if (SLocFileAbbrv == -1)
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001091 SLocFileAbbrv = CreateSLocFileAbbrev(Stream);
1092 Stream.EmitRecordWithBlob(SLocFileAbbrv, Record,
Douglas Gregorab1cef72009-04-10 03:52:48 +00001093 Content->Entry->getName(),
1094 strlen(Content->Entry->getName()));
1095 } else {
1096 // The source location entry is a buffer. The blob associated
1097 // with this entry contains the contents of the buffer.
1098 if (SLocBufferAbbrv == -1) {
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001099 SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream);
1100 SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream);
Douglas Gregorab1cef72009-04-10 03:52:48 +00001101 }
1102
1103 // We add one to the size so that we capture the trailing NULL
1104 // that is required by llvm::MemoryBuffer::getMemBuffer (on
1105 // the reader side).
1106 const llvm::MemoryBuffer *Buffer = Content->getBuffer();
1107 const char *Name = Buffer->getBufferIdentifier();
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001108 Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, Name, strlen(Name) + 1);
Douglas Gregorab1cef72009-04-10 03:52:48 +00001109 Record.clear();
1110 Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001111 Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
Douglas Gregorab1cef72009-04-10 03:52:48 +00001112 Buffer->getBufferStart(),
1113 Buffer->getBufferSize() + 1);
1114 }
1115 } else {
1116 // The source location entry is an instantiation.
1117 const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
1118 Record.push_back(Inst.getSpellingLoc().getRawEncoding());
1119 Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
1120 Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
1121
Douglas Gregor364e5802009-04-15 18:05:10 +00001122 // Compute the token length for this macro expansion.
1123 unsigned NextOffset = SourceMgr.getNextOffset();
1124 SourceManager::sloc_entry_iterator NextSLoc = SLoc;
1125 if (++NextSLoc != SLocEnd)
1126 NextOffset = NextSLoc->getOffset();
1127 Record.push_back(NextOffset - SLoc->getOffset() - 1);
1128
Douglas Gregorab1cef72009-04-10 03:52:48 +00001129 if (SLocInstantiationAbbrv == -1)
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001130 SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream);
1131 Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
Douglas Gregorab1cef72009-04-10 03:52:48 +00001132 }
1133
1134 Record.clear();
1135 }
1136
Douglas Gregor635f97f2009-04-13 16:31:14 +00001137 // Write the line table.
1138 if (SourceMgr.hasLineTable()) {
1139 LineTableInfo &LineTable = SourceMgr.getLineTable();
1140
1141 // Emit the file names
1142 Record.push_back(LineTable.getNumFilenames());
1143 for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
1144 // Emit the file name
1145 const char *Filename = LineTable.getFilename(I);
1146 unsigned FilenameLen = Filename? strlen(Filename) : 0;
1147 Record.push_back(FilenameLen);
1148 if (FilenameLen)
1149 Record.insert(Record.end(), Filename, Filename + FilenameLen);
1150 }
1151
1152 // Emit the line entries
1153 for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
1154 L != LEnd; ++L) {
1155 // Emit the file ID
1156 Record.push_back(L->first);
1157
1158 // Emit the line entries
1159 Record.push_back(L->second.size());
1160 for (std::vector<LineEntry>::iterator LE = L->second.begin(),
1161 LEEnd = L->second.end();
1162 LE != LEEnd; ++LE) {
1163 Record.push_back(LE->FileOffset);
1164 Record.push_back(LE->LineNo);
1165 Record.push_back(LE->FilenameID);
1166 Record.push_back((unsigned)LE->FileKind);
1167 Record.push_back(LE->IncludeOffset);
1168 }
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001169 Stream.EmitRecord(pch::SM_LINE_TABLE, Record);
Douglas Gregor635f97f2009-04-13 16:31:14 +00001170 }
1171 }
1172
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001173 Stream.ExitBlock();
Douglas Gregorab1cef72009-04-10 03:52:48 +00001174}
1175
Chris Lattnerffc05ed2009-04-10 17:15:23 +00001176/// \brief Writes the block containing the serialized form of the
1177/// preprocessor.
1178///
Chris Lattner850eabd2009-04-10 18:08:30 +00001179void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
Chris Lattner84b04f12009-04-10 17:16:57 +00001180 // Enter the preprocessor block.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001181 Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 3);
Chris Lattner84b04f12009-04-10 17:16:57 +00001182
Chris Lattner1b094952009-04-10 18:00:12 +00001183 // If the PCH file contains __DATE__ or __TIME__ emit a warning about this.
1184 // FIXME: use diagnostics subsystem for localization etc.
1185 if (PP.SawDateOrTime())
1186 fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
Chris Lattner84b04f12009-04-10 17:16:57 +00001187
Chris Lattner1b094952009-04-10 18:00:12 +00001188 RecordData Record;
Chris Lattner84b04f12009-04-10 17:16:57 +00001189
Chris Lattner4b21c202009-04-13 01:29:17 +00001190 // If the preprocessor __COUNTER__ value has been bumped, remember it.
1191 if (PP.getCounterValue() != 0) {
1192 Record.push_back(PP.getCounterValue());
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001193 Stream.EmitRecord(pch::PP_COUNTER_VALUE, Record);
Chris Lattner4b21c202009-04-13 01:29:17 +00001194 Record.clear();
1195 }
1196
Chris Lattner1b094952009-04-10 18:00:12 +00001197 // Loop over all the macro definitions that are live at the end of the file,
1198 // emitting each to the PP section.
1199 // FIXME: Eventually we want to emit an index so that we can lazily load
1200 // macros.
1201 for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
1202 I != E; ++I) {
Chris Lattnerdb1c81b2009-04-10 21:41:48 +00001203 // FIXME: This emits macros in hash table order, we should do it in a stable
1204 // order so that output is reproducible.
Chris Lattner1b094952009-04-10 18:00:12 +00001205 MacroInfo *MI = I->second;
1206
1207 // Don't emit builtin macros like __LINE__ to the PCH file unless they have
1208 // been redefined by the header (in which case they are not isBuiltinMacro).
1209 if (MI->isBuiltinMacro())
1210 continue;
1211
Chris Lattner29241862009-04-11 21:15:38 +00001212 AddIdentifierRef(I->first, Record);
Chris Lattner1b094952009-04-10 18:00:12 +00001213 Record.push_back(MI->getDefinitionLoc().getRawEncoding());
1214 Record.push_back(MI->isUsed());
1215
1216 unsigned Code;
1217 if (MI->isObjectLike()) {
1218 Code = pch::PP_MACRO_OBJECT_LIKE;
1219 } else {
1220 Code = pch::PP_MACRO_FUNCTION_LIKE;
1221
1222 Record.push_back(MI->isC99Varargs());
1223 Record.push_back(MI->isGNUVarargs());
1224 Record.push_back(MI->getNumArgs());
1225 for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
1226 I != E; ++I)
Chris Lattner29241862009-04-11 21:15:38 +00001227 AddIdentifierRef(*I, Record);
Chris Lattner1b094952009-04-10 18:00:12 +00001228 }
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001229 Stream.EmitRecord(Code, Record);
Chris Lattner1b094952009-04-10 18:00:12 +00001230 Record.clear();
1231
Chris Lattner850eabd2009-04-10 18:08:30 +00001232 // Emit the tokens array.
1233 for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
1234 // Note that we know that the preprocessor does not have any annotation
1235 // tokens in it because they are created by the parser, and thus can't be
1236 // in a macro definition.
1237 const Token &Tok = MI->getReplacementToken(TokNo);
1238
1239 Record.push_back(Tok.getLocation().getRawEncoding());
1240 Record.push_back(Tok.getLength());
1241
Chris Lattner850eabd2009-04-10 18:08:30 +00001242 // FIXME: When reading literal tokens, reconstruct the literal pointer if
1243 // it is needed.
Chris Lattner29241862009-04-11 21:15:38 +00001244 AddIdentifierRef(Tok.getIdentifierInfo(), Record);
Chris Lattner850eabd2009-04-10 18:08:30 +00001245
1246 // FIXME: Should translate token kind to a stable encoding.
1247 Record.push_back(Tok.getKind());
1248 // FIXME: Should translate token flags to a stable encoding.
1249 Record.push_back(Tok.getFlags());
1250
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001251 Stream.EmitRecord(pch::PP_TOKEN, Record);
Chris Lattner850eabd2009-04-10 18:08:30 +00001252 Record.clear();
1253 }
Chris Lattner1b094952009-04-10 18:00:12 +00001254
1255 }
1256
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001257 Stream.ExitBlock();
Chris Lattnerffc05ed2009-04-10 17:15:23 +00001258}
1259
1260
Douglas Gregorc34897d2009-04-09 22:27:44 +00001261/// \brief Write the representation of a type to the PCH stream.
1262void PCHWriter::WriteType(const Type *T) {
Douglas Gregorac8f2802009-04-10 17:25:41 +00001263 pch::TypeID &ID = TypeIDs[T];
Chris Lattner84b04f12009-04-10 17:16:57 +00001264 if (ID == 0) // we haven't seen this type before.
Douglas Gregorc34897d2009-04-09 22:27:44 +00001265 ID = NextTypeID++;
1266
1267 // Record the offset for this type.
1268 if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS)
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001269 TypeOffsets.push_back(Stream.GetCurrentBitNo());
Douglas Gregorc34897d2009-04-09 22:27:44 +00001270 else if (TypeOffsets.size() < ID - pch::NUM_PREDEF_TYPE_IDS) {
1271 TypeOffsets.resize(ID + 1 - pch::NUM_PREDEF_TYPE_IDS);
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001272 TypeOffsets[ID - pch::NUM_PREDEF_TYPE_IDS] = Stream.GetCurrentBitNo();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001273 }
1274
1275 RecordData Record;
1276
1277 // Emit the type's representation.
1278 PCHTypeWriter W(*this, Record);
1279 switch (T->getTypeClass()) {
1280 // For all of the concrete, non-dependent types, call the
1281 // appropriate visitor function.
1282#define TYPE(Class, Base) \
1283 case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
1284#define ABSTRACT_TYPE(Class, Base)
1285#define DEPENDENT_TYPE(Class, Base)
1286#include "clang/AST/TypeNodes.def"
1287
1288 // For all of the dependent type nodes (which only occur in C++
1289 // templates), produce an error.
1290#define TYPE(Class, Base)
1291#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1292#include "clang/AST/TypeNodes.def"
1293 assert(false && "Cannot serialize dependent type nodes");
1294 break;
1295 }
1296
1297 // Emit the serialized record.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001298 Stream.EmitRecord(W.Code, Record);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001299
1300 // Flush any expressions that were written as part of this type.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001301 FlushStmts();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001302}
1303
1304/// \brief Write a block containing all of the types.
1305void PCHWriter::WriteTypesBlock(ASTContext &Context) {
Chris Lattner84b04f12009-04-10 17:16:57 +00001306 // Enter the types block.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001307 Stream.EnterSubblock(pch::TYPES_BLOCK_ID, 2);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001308
1309 // Emit all of the types in the ASTContext
1310 for (std::vector<Type*>::const_iterator T = Context.getTypes().begin(),
1311 TEnd = Context.getTypes().end();
1312 T != TEnd; ++T) {
1313 // Builtin types are never serialized.
1314 if (isa<BuiltinType>(*T))
1315 continue;
1316
1317 WriteType(*T);
1318 }
1319
1320 // Exit the types block
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001321 Stream.ExitBlock();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001322}
1323
1324/// \brief Write the block containing all of the declaration IDs
1325/// lexically declared within the given DeclContext.
1326///
1327/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
1328/// bistream, or 0 if no block was written.
1329uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
1330 DeclContext *DC) {
Douglas Gregorac8f2802009-04-10 17:25:41 +00001331 if (DC->decls_empty(Context))
Douglas Gregorc34897d2009-04-09 22:27:44 +00001332 return 0;
1333
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001334 uint64_t Offset = Stream.GetCurrentBitNo();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001335 RecordData Record;
1336 for (DeclContext::decl_iterator D = DC->decls_begin(Context),
1337 DEnd = DC->decls_end(Context);
1338 D != DEnd; ++D)
1339 AddDeclRef(*D, Record);
1340
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001341 Stream.EmitRecord(pch::DECL_CONTEXT_LEXICAL, Record);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001342 return Offset;
1343}
1344
1345/// \brief Write the block containing all of the declaration IDs
1346/// visible from the given DeclContext.
1347///
1348/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
1349/// bistream, or 0 if no block was written.
1350uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
1351 DeclContext *DC) {
1352 if (DC->getPrimaryContext() != DC)
1353 return 0;
1354
1355 // Force the DeclContext to build a its name-lookup table.
1356 DC->lookup(Context, DeclarationName());
1357
1358 // Serialize the contents of the mapping used for lookup. Note that,
1359 // although we have two very different code paths, the serialized
1360 // representation is the same for both cases: a declaration name,
1361 // followed by a size, followed by references to the visible
1362 // declarations that have that name.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001363 uint64_t Offset = Stream.GetCurrentBitNo();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001364 RecordData Record;
1365 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
Douglas Gregor982365e2009-04-13 21:20:57 +00001366 if (!Map)
1367 return 0;
1368
Douglas Gregorc34897d2009-04-09 22:27:44 +00001369 for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
1370 D != DEnd; ++D) {
1371 AddDeclarationName(D->first, Record);
1372 DeclContext::lookup_result Result = D->second.getLookupResult(Context);
1373 Record.push_back(Result.second - Result.first);
1374 for(; Result.first != Result.second; ++Result.first)
1375 AddDeclRef(*Result.first, Record);
1376 }
1377
1378 if (Record.size() == 0)
1379 return 0;
1380
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001381 Stream.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001382 return Offset;
1383}
1384
1385/// \brief Write a block containing all of the declarations.
1386void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
Chris Lattner84b04f12009-04-10 17:16:57 +00001387 // Enter the declarations block.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001388 Stream.EnterSubblock(pch::DECLS_BLOCK_ID, 2);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001389
1390 // Emit all of the declarations.
1391 RecordData Record;
1392 PCHDeclWriter W(*this, Record);
1393 while (!DeclsToEmit.empty()) {
1394 // Pull the next declaration off the queue
1395 Decl *D = DeclsToEmit.front();
1396 DeclsToEmit.pop();
1397
1398 // If this declaration is also a DeclContext, write blocks for the
1399 // declarations that lexically stored inside its context and those
1400 // declarations that are visible from its context. These blocks
1401 // are written before the declaration itself so that we can put
1402 // their offsets into the record for the declaration.
1403 uint64_t LexicalOffset = 0;
1404 uint64_t VisibleOffset = 0;
1405 DeclContext *DC = dyn_cast<DeclContext>(D);
1406 if (DC) {
1407 LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
1408 VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
1409 }
1410
1411 // Determine the ID for this declaration
Douglas Gregorac8f2802009-04-10 17:25:41 +00001412 pch::DeclID ID = DeclIDs[D];
Douglas Gregorc34897d2009-04-09 22:27:44 +00001413 if (ID == 0)
1414 ID = DeclIDs.size();
1415
1416 unsigned Index = ID - 1;
1417
1418 // Record the offset for this declaration
1419 if (DeclOffsets.size() == Index)
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001420 DeclOffsets.push_back(Stream.GetCurrentBitNo());
Douglas Gregorc34897d2009-04-09 22:27:44 +00001421 else if (DeclOffsets.size() < Index) {
1422 DeclOffsets.resize(Index+1);
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001423 DeclOffsets[Index] = Stream.GetCurrentBitNo();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001424 }
1425
1426 // Build and emit a record for this declaration
1427 Record.clear();
1428 W.Code = (pch::DeclCode)0;
1429 W.Visit(D);
1430 if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
Douglas Gregor631f6c62009-04-14 00:24:19 +00001431 assert(W.Code && "Unhandled declaration kind while generating PCH");
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001432 Stream.EmitRecord(W.Code, Record);
Douglas Gregor631f6c62009-04-14 00:24:19 +00001433
Douglas Gregor1c507882009-04-15 21:30:51 +00001434 // If the declaration had any attributes, write them now.
1435 if (D->hasAttrs())
1436 WriteAttributeRecord(D->getAttrs());
1437
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001438 // Flush any expressions that were written as part of this declaration.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001439 FlushStmts();
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001440
Douglas Gregor631f6c62009-04-14 00:24:19 +00001441 // Note external declarations so that we can add them to a record
1442 // in the PCH file later.
1443 if (isa<FileScopeAsmDecl>(D))
1444 ExternalDefinitions.push_back(ID);
1445 else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
1446 if (// Non-static file-scope variables with initializers or that
1447 // are tentative definitions.
1448 (Var->isFileVarDecl() &&
1449 (Var->getInit() || Var->getStorageClass() == VarDecl::None)) ||
1450 // Out-of-line definitions of static data members (C++).
1451 (Var->getDeclContext()->isRecord() &&
1452 !Var->getLexicalDeclContext()->isRecord() &&
1453 Var->getStorageClass() == VarDecl::Static))
1454 ExternalDefinitions.push_back(ID);
1455 } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) {
1456 if (Func->isThisDeclarationADefinition() &&
1457 Func->getStorageClass() != FunctionDecl::Static &&
1458 !Func->isInline())
1459 ExternalDefinitions.push_back(ID);
1460 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001461 }
1462
1463 // Exit the declarations block
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001464 Stream.ExitBlock();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001465}
1466
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001467/// \brief Write the identifier table into the PCH file.
1468///
1469/// The identifier table consists of a blob containing string data
1470/// (the actual identifiers themselves) and a separate "offsets" index
1471/// that maps identifier IDs to locations within the blob.
1472void PCHWriter::WriteIdentifierTable() {
1473 using namespace llvm;
1474
1475 // Create and write out the blob that contains the identifier
1476 // strings.
1477 RecordData IdentOffsets;
1478 IdentOffsets.resize(IdentifierIDs.size());
1479 {
1480 // Create the identifier string data.
1481 std::vector<char> Data;
1482 Data.push_back(0); // Data must not be empty.
1483 for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator
1484 ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
1485 ID != IDEnd; ++ID) {
1486 assert(ID->first && "NULL identifier in identifier table");
1487
1488 // Make sure we're starting on an odd byte. The PCH reader
1489 // expects the low bit to be set on all of the offsets.
1490 if ((Data.size() & 0x01) == 0)
1491 Data.push_back((char)0);
1492
1493 IdentOffsets[ID->second - 1] = Data.size();
1494 Data.insert(Data.end(),
1495 ID->first->getName(),
1496 ID->first->getName() + ID->first->getLength());
1497 Data.push_back((char)0);
1498 }
1499
1500 // Create a blob abbreviation
1501 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
1502 Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE));
1503 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Triple name
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001504 unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001505
1506 // Write the identifier table
1507 RecordData Record;
1508 Record.push_back(pch::IDENTIFIER_TABLE);
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001509 Stream.EmitRecordWithBlob(IDTableAbbrev, Record, &Data.front(), Data.size());
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001510 }
1511
1512 // Write the offsets table for identifier IDs.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001513 Stream.EmitRecord(pch::IDENTIFIER_OFFSET, IdentOffsets);
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001514}
1515
Douglas Gregor1c507882009-04-15 21:30:51 +00001516/// \brief Write a record containing the given attributes.
1517void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
1518 RecordData Record;
1519 for (; Attr; Attr = Attr->getNext()) {
1520 Record.push_back(Attr->getKind()); // FIXME: stable encoding
1521 Record.push_back(Attr->isInherited());
1522 switch (Attr->getKind()) {
1523 case Attr::Alias:
1524 AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
1525 break;
1526
1527 case Attr::Aligned:
1528 Record.push_back(cast<AlignedAttr>(Attr)->getAlignment());
1529 break;
1530
1531 case Attr::AlwaysInline:
1532 break;
1533
1534 case Attr::AnalyzerNoReturn:
1535 break;
1536
1537 case Attr::Annotate:
1538 AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record);
1539 break;
1540
1541 case Attr::AsmLabel:
1542 AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
1543 break;
1544
1545 case Attr::Blocks:
1546 Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
1547 break;
1548
1549 case Attr::Cleanup:
1550 AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
1551 break;
1552
1553 case Attr::Const:
1554 break;
1555
1556 case Attr::Constructor:
1557 Record.push_back(cast<ConstructorAttr>(Attr)->getPriority());
1558 break;
1559
1560 case Attr::DLLExport:
1561 case Attr::DLLImport:
1562 case Attr::Deprecated:
1563 break;
1564
1565 case Attr::Destructor:
1566 Record.push_back(cast<DestructorAttr>(Attr)->getPriority());
1567 break;
1568
1569 case Attr::FastCall:
1570 break;
1571
1572 case Attr::Format: {
1573 const FormatAttr *Format = cast<FormatAttr>(Attr);
1574 AddString(Format->getType(), Record);
1575 Record.push_back(Format->getFormatIdx());
1576 Record.push_back(Format->getFirstArg());
1577 break;
1578 }
1579
1580 case Attr::GNUCInline:
1581 case Attr::IBOutletKind:
1582 case Attr::NoReturn:
1583 case Attr::NoThrow:
1584 case Attr::Nodebug:
1585 case Attr::Noinline:
1586 break;
1587
1588 case Attr::NonNull: {
1589 const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
1590 Record.push_back(NonNull->size());
1591 Record.insert(Record.end(), NonNull->begin(), NonNull->end());
1592 break;
1593 }
1594
1595 case Attr::ObjCException:
1596 case Attr::ObjCNSObject:
1597 case Attr::Overloadable:
1598 break;
1599
1600 case Attr::Packed:
1601 Record.push_back(cast<PackedAttr>(Attr)->getAlignment());
1602 break;
1603
1604 case Attr::Pure:
1605 break;
1606
1607 case Attr::Regparm:
1608 Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
1609 break;
1610
1611 case Attr::Section:
1612 AddString(cast<SectionAttr>(Attr)->getName(), Record);
1613 break;
1614
1615 case Attr::StdCall:
1616 case Attr::TransparentUnion:
1617 case Attr::Unavailable:
1618 case Attr::Unused:
1619 case Attr::Used:
1620 break;
1621
1622 case Attr::Visibility:
1623 // FIXME: stable encoding
1624 Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility());
1625 break;
1626
1627 case Attr::WarnUnusedResult:
1628 case Attr::Weak:
1629 case Attr::WeakImport:
1630 break;
1631 }
1632 }
1633
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001634 Stream.EmitRecord(pch::DECL_ATTR, Record);
Douglas Gregor1c507882009-04-15 21:30:51 +00001635}
1636
1637void PCHWriter::AddString(const std::string &Str, RecordData &Record) {
1638 Record.push_back(Str.size());
1639 Record.insert(Record.end(), Str.begin(), Str.end());
1640}
1641
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001642PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
1643 : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS) { }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001644
Chris Lattner850eabd2009-04-10 18:08:30 +00001645void PCHWriter::WritePCH(ASTContext &Context, const Preprocessor &PP) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001646 // Emit the file header.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001647 Stream.Emit((unsigned)'C', 8);
1648 Stream.Emit((unsigned)'P', 8);
1649 Stream.Emit((unsigned)'C', 8);
1650 Stream.Emit((unsigned)'H', 8);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001651
1652 // The translation unit is the first declaration we'll emit.
1653 DeclIDs[Context.getTranslationUnitDecl()] = 1;
1654 DeclsToEmit.push(Context.getTranslationUnitDecl());
1655
1656 // Write the remaining PCH contents.
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001657 Stream.EnterSubblock(pch::PCH_BLOCK_ID, 3);
Douglas Gregorb5887f32009-04-10 21:16:55 +00001658 WriteTargetTriple(Context.Target);
Douglas Gregor179cfb12009-04-10 20:39:37 +00001659 WriteLanguageOptions(Context.getLangOptions());
Douglas Gregorab1cef72009-04-10 03:52:48 +00001660 WriteSourceManagerBlock(Context.getSourceManager());
Chris Lattnerffc05ed2009-04-10 17:15:23 +00001661 WritePreprocessor(PP);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001662 WriteTypesBlock(Context);
1663 WriteDeclsBlock(Context);
Douglas Gregor631f6c62009-04-14 00:24:19 +00001664 WriteIdentifierTable();
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001665 Stream.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
1666 Stream.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
Douglas Gregor631f6c62009-04-14 00:24:19 +00001667 if (!ExternalDefinitions.empty())
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001668 Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions);
1669 Stream.ExitBlock();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001670}
1671
1672void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
1673 Record.push_back(Loc.getRawEncoding());
1674}
1675
1676void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
1677 Record.push_back(Value.getBitWidth());
1678 unsigned N = Value.getNumWords();
1679 const uint64_t* Words = Value.getRawData();
1680 for (unsigned I = 0; I != N; ++I)
1681 Record.push_back(Words[I]);
1682}
1683
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001684void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) {
1685 Record.push_back(Value.isUnsigned());
1686 AddAPInt(Value, Record);
1687}
1688
Douglas Gregore2f37202009-04-14 21:55:33 +00001689void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) {
1690 AddAPInt(Value.bitcastToAPInt(), Record);
1691}
1692
Douglas Gregorc34897d2009-04-09 22:27:44 +00001693void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001694 if (II == 0) {
1695 Record.push_back(0);
1696 return;
1697 }
1698
1699 pch::IdentID &ID = IdentifierIDs[II];
1700 if (ID == 0)
1701 ID = IdentifierIDs.size();
1702
1703 Record.push_back(ID);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001704}
1705
1706void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
1707 if (T.isNull()) {
1708 Record.push_back(pch::PREDEF_TYPE_NULL_ID);
1709 return;
1710 }
1711
1712 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001713 pch::TypeID ID = 0;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001714 switch (BT->getKind()) {
1715 case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break;
1716 case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break;
1717 case BuiltinType::Char_U: ID = pch::PREDEF_TYPE_CHAR_U_ID; break;
1718 case BuiltinType::UChar: ID = pch::PREDEF_TYPE_UCHAR_ID; break;
1719 case BuiltinType::UShort: ID = pch::PREDEF_TYPE_USHORT_ID; break;
1720 case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break;
1721 case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break;
1722 case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break;
1723 case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break;
1724 case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break;
1725 case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break;
1726 case BuiltinType::Short: ID = pch::PREDEF_TYPE_SHORT_ID; break;
1727 case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break;
1728 case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break;
1729 case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break;
1730 case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break;
1731 case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break;
1732 case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
1733 case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break;
1734 case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
1735 }
1736
1737 Record.push_back((ID << 3) | T.getCVRQualifiers());
1738 return;
1739 }
1740
Douglas Gregorac8f2802009-04-10 17:25:41 +00001741 pch::TypeID &ID = TypeIDs[T.getTypePtr()];
Douglas Gregorc34897d2009-04-09 22:27:44 +00001742 if (ID == 0) // we haven't seen this type before
1743 ID = NextTypeID++;
1744
1745 // Encode the type qualifiers in the type reference.
1746 Record.push_back((ID << 3) | T.getCVRQualifiers());
1747}
1748
1749void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
1750 if (D == 0) {
1751 Record.push_back(0);
1752 return;
1753 }
1754
Douglas Gregorac8f2802009-04-10 17:25:41 +00001755 pch::DeclID &ID = DeclIDs[D];
Douglas Gregorc34897d2009-04-09 22:27:44 +00001756 if (ID == 0) {
1757 // We haven't seen this declaration before. Give it a new ID and
1758 // enqueue it in the list of declarations to emit.
1759 ID = DeclIDs.size();
1760 DeclsToEmit.push(const_cast<Decl *>(D));
1761 }
1762
1763 Record.push_back(ID);
1764}
1765
1766void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
1767 Record.push_back(Name.getNameKind());
1768 switch (Name.getNameKind()) {
1769 case DeclarationName::Identifier:
1770 AddIdentifierRef(Name.getAsIdentifierInfo(), Record);
1771 break;
1772
1773 case DeclarationName::ObjCZeroArgSelector:
1774 case DeclarationName::ObjCOneArgSelector:
1775 case DeclarationName::ObjCMultiArgSelector:
1776 assert(false && "Serialization of Objective-C selectors unavailable");
1777 break;
1778
1779 case DeclarationName::CXXConstructorName:
1780 case DeclarationName::CXXDestructorName:
1781 case DeclarationName::CXXConversionFunctionName:
1782 AddTypeRef(Name.getCXXNameType(), Record);
1783 break;
1784
1785 case DeclarationName::CXXOperatorName:
1786 Record.push_back(Name.getCXXOverloadedOperator());
1787 break;
1788
1789 case DeclarationName::CXXUsingDirective:
1790 // No extra data to emit
1791 break;
1792 }
1793}
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001794
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001795/// \brief Write the given substatement or subexpression to the
1796/// bitstream.
1797void PCHWriter::WriteSubStmt(Stmt *S) {
Douglas Gregora151ba42009-04-14 23:32:43 +00001798 RecordData Record;
1799 PCHStmtWriter Writer(*this, Record);
1800
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001801 if (!S) {
1802 Stream.EmitRecord(pch::STMT_NULL_PTR, Record);
Douglas Gregora151ba42009-04-14 23:32:43 +00001803 return;
1804 }
1805
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001806 Writer.Code = pch::STMT_NULL_PTR;
1807 Writer.Visit(S);
1808 assert(Writer.Code != pch::STMT_NULL_PTR &&
Douglas Gregora151ba42009-04-14 23:32:43 +00001809 "Unhandled expression writing PCH file");
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001810 Stream.EmitRecord(Writer.Code, Record);
Douglas Gregora151ba42009-04-14 23:32:43 +00001811}
1812
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001813/// \brief Flush all of the statements that have been added to the
1814/// queue via AddStmt().
1815void PCHWriter::FlushStmts() {
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001816 RecordData Record;
1817 PCHStmtWriter Writer(*this, Record);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001818
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001819 for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) {
1820 Stmt *S = StmtsToEmit[I];
Douglas Gregora151ba42009-04-14 23:32:43 +00001821
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001822 if (!S) {
1823 Stream.EmitRecord(pch::STMT_NULL_PTR, Record);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001824 continue;
1825 }
1826
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001827 Writer.Code = pch::STMT_NULL_PTR;
1828 Writer.Visit(S);
1829 assert(Writer.Code != pch::STMT_NULL_PTR &&
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001830 "Unhandled expression writing PCH file");
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001831 Stream.EmitRecord(Writer.Code, Record);
Douglas Gregora151ba42009-04-14 23:32:43 +00001832
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001833 assert(N == StmtsToEmit.size() &&
1834 "Substatement writen via AddStmt rather than WriteSubStmt!");
Douglas Gregora151ba42009-04-14 23:32:43 +00001835
1836 // Note that we are at the end of a full expression. Any
1837 // expression records that follow this one are part of a different
1838 // expression.
1839 Record.clear();
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001840 Stream.EmitRecord(pch::STMT_STOP, Record);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001841 }
Douglas Gregora151ba42009-04-14 23:32:43 +00001842
Douglas Gregorc72f6c82009-04-16 22:23:12 +00001843 StmtsToEmit.clear();
Douglas Gregor22d2dcd2009-04-17 16:34:57 +00001844 SwitchCaseIDs.clear();
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001845}
Douglas Gregor9c4782a2009-04-17 00:04:06 +00001846
1847unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) {
1848 assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() &&
1849 "SwitchCase recorded twice");
1850 unsigned NextID = SwitchCaseIDs.size();
1851 SwitchCaseIDs[S] = NextID;
1852 return NextID;
1853}
1854
1855unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) {
1856 assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() &&
1857 "SwitchCase hasn't been seen yet");
1858 return SwitchCaseIDs[S];
1859}