blob: d4961e4e744ff7141b02b801b8e9196cd418d339 [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"
19#include "clang/AST/Type.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000020#include "clang/Basic/FileManager.h"
21#include "clang/Basic/SourceManager.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000022#include "llvm/Bitcode/BitstreamWriter.h"
23#include "llvm/Support/Compiler.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000024#include "llvm/Support/MemoryBuffer.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000025
26using namespace clang;
27
28//===----------------------------------------------------------------------===//
29// Type serialization
30//===----------------------------------------------------------------------===//
31namespace {
32 class VISIBILITY_HIDDEN PCHTypeWriter {
33 PCHWriter &Writer;
34 PCHWriter::RecordData &Record;
35
36 public:
37 /// \brief Type code that corresponds to the record generated.
38 pch::TypeCode Code;
39
40 PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
41 : Writer(Writer), Record(Record) { }
42
43 void VisitArrayType(const ArrayType *T);
44 void VisitFunctionType(const FunctionType *T);
45 void VisitTagType(const TagType *T);
46
47#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
48#define ABSTRACT_TYPE(Class, Base)
49#define DEPENDENT_TYPE(Class, Base)
50#include "clang/AST/TypeNodes.def"
51 };
52}
53
54void PCHTypeWriter::VisitExtQualType(const ExtQualType *T) {
55 Writer.AddTypeRef(QualType(T->getBaseType(), 0), Record);
56 Record.push_back(T->getObjCGCAttr()); // FIXME: use stable values
57 Record.push_back(T->getAddressSpace());
58 Code = pch::TYPE_EXT_QUAL;
59}
60
61void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
62 assert(false && "Built-in types are never serialized");
63}
64
65void PCHTypeWriter::VisitFixedWidthIntType(const FixedWidthIntType *T) {
66 Record.push_back(T->getWidth());
67 Record.push_back(T->isSigned());
68 Code = pch::TYPE_FIXED_WIDTH_INT;
69}
70
71void PCHTypeWriter::VisitComplexType(const ComplexType *T) {
72 Writer.AddTypeRef(T->getElementType(), Record);
73 Code = pch::TYPE_COMPLEX;
74}
75
76void PCHTypeWriter::VisitPointerType(const PointerType *T) {
77 Writer.AddTypeRef(T->getPointeeType(), Record);
78 Code = pch::TYPE_POINTER;
79}
80
81void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
82 Writer.AddTypeRef(T->getPointeeType(), Record);
83 Code = pch::TYPE_BLOCK_POINTER;
84}
85
86void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
87 Writer.AddTypeRef(T->getPointeeType(), Record);
88 Code = pch::TYPE_LVALUE_REFERENCE;
89}
90
91void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
92 Writer.AddTypeRef(T->getPointeeType(), Record);
93 Code = pch::TYPE_RVALUE_REFERENCE;
94}
95
96void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
97 Writer.AddTypeRef(T->getPointeeType(), Record);
98 Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
99 Code = pch::TYPE_MEMBER_POINTER;
100}
101
102void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
103 Writer.AddTypeRef(T->getElementType(), Record);
104 Record.push_back(T->getSizeModifier()); // FIXME: stable values
105 Record.push_back(T->getIndexTypeQualifier()); // FIXME: stable values
106}
107
108void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
109 VisitArrayType(T);
110 Writer.AddAPInt(T->getSize(), Record);
111 Code = pch::TYPE_CONSTANT_ARRAY;
112}
113
114void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
115 VisitArrayType(T);
116 Code = pch::TYPE_INCOMPLETE_ARRAY;
117}
118
119void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
120 VisitArrayType(T);
121 // FIXME: Serialize array size expression.
122 assert(false && "Cannot serialize variable-length arrays");
123 Code = pch::TYPE_VARIABLE_ARRAY;
124}
125
126void PCHTypeWriter::VisitVectorType(const VectorType *T) {
127 Writer.AddTypeRef(T->getElementType(), Record);
128 Record.push_back(T->getNumElements());
129 Code = pch::TYPE_VECTOR;
130}
131
132void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
133 VisitVectorType(T);
134 Code = pch::TYPE_EXT_VECTOR;
135}
136
137void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
138 Writer.AddTypeRef(T->getResultType(), Record);
139}
140
141void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
142 VisitFunctionType(T);
143 Code = pch::TYPE_FUNCTION_NO_PROTO;
144}
145
146void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
147 VisitFunctionType(T);
148 Record.push_back(T->getNumArgs());
149 for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
150 Writer.AddTypeRef(T->getArgType(I), Record);
151 Record.push_back(T->isVariadic());
152 Record.push_back(T->getTypeQuals());
153 Code = pch::TYPE_FUNCTION_PROTO;
154}
155
156void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
157 Writer.AddDeclRef(T->getDecl(), Record);
158 Code = pch::TYPE_TYPEDEF;
159}
160
161void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
162 // FIXME: serialize the typeof expression
163 assert(false && "Cannot serialize typeof(expr)");
164 Code = pch::TYPE_TYPEOF_EXPR;
165}
166
167void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) {
168 Writer.AddTypeRef(T->getUnderlyingType(), Record);
169 Code = pch::TYPE_TYPEOF;
170}
171
172void PCHTypeWriter::VisitTagType(const TagType *T) {
173 Writer.AddDeclRef(T->getDecl(), Record);
174 assert(!T->isBeingDefined() &&
175 "Cannot serialize in the middle of a type definition");
176}
177
178void PCHTypeWriter::VisitRecordType(const RecordType *T) {
179 VisitTagType(T);
180 Code = pch::TYPE_RECORD;
181}
182
183void PCHTypeWriter::VisitEnumType(const EnumType *T) {
184 VisitTagType(T);
185 Code = pch::TYPE_ENUM;
186}
187
188void
189PCHTypeWriter::VisitTemplateSpecializationType(
190 const TemplateSpecializationType *T) {
191 // FIXME: Serialize this type
192 assert(false && "Cannot serialize template specialization types");
193}
194
195void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) {
196 // FIXME: Serialize this type
197 assert(false && "Cannot serialize qualified name types");
198}
199
200void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
201 Writer.AddDeclRef(T->getDecl(), Record);
202 Code = pch::TYPE_OBJC_INTERFACE;
203}
204
205void
206PCHTypeWriter::VisitObjCQualifiedInterfaceType(
207 const ObjCQualifiedInterfaceType *T) {
208 VisitObjCInterfaceType(T);
209 Record.push_back(T->getNumProtocols());
210 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
211 Writer.AddDeclRef(T->getProtocol(I), Record);
212 Code = pch::TYPE_OBJC_QUALIFIED_INTERFACE;
213}
214
215void PCHTypeWriter::VisitObjCQualifiedIdType(const ObjCQualifiedIdType *T) {
216 Record.push_back(T->getNumProtocols());
217 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
218 Writer.AddDeclRef(T->getProtocols(I), Record);
219 Code = pch::TYPE_OBJC_QUALIFIED_ID;
220}
221
222void
223PCHTypeWriter::VisitObjCQualifiedClassType(const ObjCQualifiedClassType *T) {
224 Record.push_back(T->getNumProtocols());
225 for (unsigned I = 0, N = T->getNumProtocols(); I != N; ++I)
226 Writer.AddDeclRef(T->getProtocols(I), Record);
227 Code = pch::TYPE_OBJC_QUALIFIED_CLASS;
228}
229
230//===----------------------------------------------------------------------===//
231// Declaration serialization
232//===----------------------------------------------------------------------===//
233namespace {
234 class VISIBILITY_HIDDEN PCHDeclWriter
235 : public DeclVisitor<PCHDeclWriter, void> {
236
237 PCHWriter &Writer;
238 PCHWriter::RecordData &Record;
239
240 public:
241 pch::DeclCode Code;
242
243 PCHDeclWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
244 : Writer(Writer), Record(Record) { }
245
246 void VisitDecl(Decl *D);
247 void VisitTranslationUnitDecl(TranslationUnitDecl *D);
248 void VisitNamedDecl(NamedDecl *D);
249 void VisitTypeDecl(TypeDecl *D);
250 void VisitTypedefDecl(TypedefDecl *D);
251 void VisitValueDecl(ValueDecl *D);
252 void VisitVarDecl(VarDecl *D);
253
254 void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
255 uint64_t VisibleOffset);
256 };
257}
258
259void PCHDeclWriter::VisitDecl(Decl *D) {
260 Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
261 Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
262 Writer.AddSourceLocation(D->getLocation(), Record);
263 Record.push_back(D->isInvalidDecl());
264 // FIXME: hasAttrs
265 Record.push_back(D->isImplicit());
266 Record.push_back(D->getAccess());
267}
268
269void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
270 VisitDecl(D);
271 Code = pch::DECL_TRANSLATION_UNIT;
272}
273
274void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
275 VisitDecl(D);
276 Writer.AddDeclarationName(D->getDeclName(), Record);
277}
278
279void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
280 VisitNamedDecl(D);
281 Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
282}
283
284void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
285 VisitTypeDecl(D);
286 Writer.AddTypeRef(D->getUnderlyingType(), Record);
287 Code = pch::DECL_TYPEDEF;
288}
289
290void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
291 VisitNamedDecl(D);
292 Writer.AddTypeRef(D->getType(), Record);
293}
294
295void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
296 VisitValueDecl(D);
297 Record.push_back(D->getStorageClass());
298 Record.push_back(D->isThreadSpecified());
299 Record.push_back(D->hasCXXDirectInitializer());
300 Record.push_back(D->isDeclaredInCondition());
301 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
302 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
303 // FIXME: emit initializer
304 Code = pch::DECL_VAR;
305}
306
307/// \brief Emit the DeclContext part of a declaration context decl.
308///
309/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
310/// block for this declaration context is stored. May be 0 to indicate
311/// that there are no declarations stored within this context.
312///
313/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
314/// block for this declaration context is stored. May be 0 to indicate
315/// that there are no declarations visible from this context. Note
316/// that this value will not be emitted for non-primary declaration
317/// contexts.
318void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
319 uint64_t VisibleOffset) {
320 Record.push_back(LexicalOffset);
321 if (DC->getPrimaryContext() == DC)
322 Record.push_back(VisibleOffset);
323}
324
325//===----------------------------------------------------------------------===//
326// PCHWriter Implementation
327//===----------------------------------------------------------------------===//
328
Douglas Gregorab1cef72009-04-10 03:52:48 +0000329//===----------------------------------------------------------------------===//
330// Source Manager Serialization
331//===----------------------------------------------------------------------===//
332
333/// \brief Create an abbreviation for the SLocEntry that refers to a
334/// file.
335static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &S) {
336 using namespace llvm;
337 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
338 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
339 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
340 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
341 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
342 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
343 // FIXME: Need an actual encoding for the line directives; maybe
344 // this should be an array?
345 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
346 return S.EmitAbbrev(Abbrev);
347}
348
349/// \brief Create an abbreviation for the SLocEntry that refers to a
350/// buffer.
351static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &S) {
352 using namespace llvm;
353 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
354 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
355 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
356 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
357 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
358 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
359 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
360 return S.EmitAbbrev(Abbrev);
361}
362
363/// \brief Create an abbreviation for the SLocEntry that refers to a
364/// buffer's blob.
365static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &S) {
366 using namespace llvm;
367 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
368 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
369 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
370 return S.EmitAbbrev(Abbrev);
371}
372
373/// \brief Create an abbreviation for the SLocEntry that refers to an
374/// buffer.
375static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &S) {
376 using namespace llvm;
377 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
378 Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
379 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
380 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
381 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
382 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
383 return S.EmitAbbrev(Abbrev);
384}
385
386/// \brief Writes the block containing the serialized form of the
387/// source manager.
388///
389/// TODO: We should probably use an on-disk hash table (stored in a
390/// blob), indexed based on the file name, so that we only create
391/// entries for files that we actually need. In the common case (no
392/// errors), we probably won't have to create file entries for any of
393/// the files in the AST.
394void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) {
395 // Enter the types block
396 S.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
397
398 // Abbreviations for the various kinds of source-location entries.
399 int SLocFileAbbrv = -1;
400 int SLocBufferAbbrv = -1;
401 int SLocBufferBlobAbbrv = -1;
402 int SLocInstantiationAbbrv = -1;
403
404 // Write out the source location entry table. We skip the first
405 // entry, which is always the same dummy entry.
406 RecordData Record;
407 for (SourceManager::sloc_entry_iterator
408 SLoc = SourceMgr.sloc_entry_begin() + 1,
409 SLocEnd = SourceMgr.sloc_entry_end();
410 SLoc != SLocEnd; ++SLoc) {
411 // Figure out which record code to use.
412 unsigned Code;
413 if (SLoc->isFile()) {
414 if (SLoc->getFile().getContentCache()->Entry)
415 Code = pch::SM_SLOC_FILE_ENTRY;
416 else
417 Code = pch::SM_SLOC_BUFFER_ENTRY;
418 } else
419 Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
420 Record.push_back(Code);
421
422 Record.push_back(SLoc->getOffset());
423 if (SLoc->isFile()) {
424 const SrcMgr::FileInfo &File = SLoc->getFile();
425 Record.push_back(File.getIncludeLoc().getRawEncoding());
426 Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
427 Record.push_back(File.hasLineDirectives()); // FIXME: encode the
428 // line directives?
429
430 const SrcMgr::ContentCache *Content = File.getContentCache();
431 if (Content->Entry) {
432 // The source location entry is a file. The blob associated
433 // with this entry is the file name.
434 if (SLocFileAbbrv == -1)
435 SLocFileAbbrv = CreateSLocFileAbbrev(S);
436 S.EmitRecordWithBlob(SLocFileAbbrv, Record,
437 Content->Entry->getName(),
438 strlen(Content->Entry->getName()));
439 } else {
440 // The source location entry is a buffer. The blob associated
441 // with this entry contains the contents of the buffer.
442 if (SLocBufferAbbrv == -1) {
443 SLocBufferAbbrv = CreateSLocBufferAbbrev(S);
444 SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(S);
445 }
446
447 // We add one to the size so that we capture the trailing NULL
448 // that is required by llvm::MemoryBuffer::getMemBuffer (on
449 // the reader side).
450 const llvm::MemoryBuffer *Buffer = Content->getBuffer();
451 const char *Name = Buffer->getBufferIdentifier();
452 S.EmitRecordWithBlob(SLocBufferAbbrv, Record, Name, strlen(Name) + 1);
453 Record.clear();
454 Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
455 S.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
456 Buffer->getBufferStart(),
457 Buffer->getBufferSize() + 1);
458 }
459 } else {
460 // The source location entry is an instantiation.
461 const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
462 Record.push_back(Inst.getSpellingLoc().getRawEncoding());
463 Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
464 Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
465
466 if (SLocInstantiationAbbrv == -1)
467 SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(S);
468 S.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
469 }
470
471 Record.clear();
472 }
473
474 S.ExitBlock();
475}
476
Douglas Gregorc34897d2009-04-09 22:27:44 +0000477/// \brief Write the representation of a type to the PCH stream.
478void PCHWriter::WriteType(const Type *T) {
479 pch::ID &ID = TypeIDs[T];
480 if (ID == 0) // we haven't seen this type before
481 ID = NextTypeID++;
482
483 // Record the offset for this type.
484 if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS)
485 TypeOffsets.push_back(S.GetCurrentBitNo());
486 else if (TypeOffsets.size() < ID - pch::NUM_PREDEF_TYPE_IDS) {
487 TypeOffsets.resize(ID + 1 - pch::NUM_PREDEF_TYPE_IDS);
488 TypeOffsets[ID - pch::NUM_PREDEF_TYPE_IDS] = S.GetCurrentBitNo();
489 }
490
491 RecordData Record;
492
493 // Emit the type's representation.
494 PCHTypeWriter W(*this, Record);
495 switch (T->getTypeClass()) {
496 // For all of the concrete, non-dependent types, call the
497 // appropriate visitor function.
498#define TYPE(Class, Base) \
499 case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
500#define ABSTRACT_TYPE(Class, Base)
501#define DEPENDENT_TYPE(Class, Base)
502#include "clang/AST/TypeNodes.def"
503
504 // For all of the dependent type nodes (which only occur in C++
505 // templates), produce an error.
506#define TYPE(Class, Base)
507#define DEPENDENT_TYPE(Class, Base) case Type::Class:
508#include "clang/AST/TypeNodes.def"
509 assert(false && "Cannot serialize dependent type nodes");
510 break;
511 }
512
513 // Emit the serialized record.
514 S.EmitRecord(W.Code, Record);
515}
516
517/// \brief Write a block containing all of the types.
518void PCHWriter::WriteTypesBlock(ASTContext &Context) {
519 // Enter the types block
520 S.EnterSubblock(pch::TYPES_BLOCK_ID, 2);
521
522 // Emit all of the types in the ASTContext
523 for (std::vector<Type*>::const_iterator T = Context.getTypes().begin(),
524 TEnd = Context.getTypes().end();
525 T != TEnd; ++T) {
526 // Builtin types are never serialized.
527 if (isa<BuiltinType>(*T))
528 continue;
529
530 WriteType(*T);
531 }
532
533 // Exit the types block
534 S.ExitBlock();
535
536 // Write the type offsets block
537 S.EnterSubblock(pch::TYPE_OFFSETS_BLOCK_ID, 2);
538 S.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
539 S.ExitBlock();
540}
541
542/// \brief Write the block containing all of the declaration IDs
543/// lexically declared within the given DeclContext.
544///
545/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
546/// bistream, or 0 if no block was written.
547uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
548 DeclContext *DC) {
549 if (DC->decls_begin(Context) == DC->decls_end(Context))
550 return 0;
551
552 uint64_t Offset = S.GetCurrentBitNo();
553 RecordData Record;
554 for (DeclContext::decl_iterator D = DC->decls_begin(Context),
555 DEnd = DC->decls_end(Context);
556 D != DEnd; ++D)
557 AddDeclRef(*D, Record);
558
559 S.EmitRecord(pch::DECL_CONTEXT_LEXICAL, Record);
560 return Offset;
561}
562
563/// \brief Write the block containing all of the declaration IDs
564/// visible from the given DeclContext.
565///
566/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
567/// bistream, or 0 if no block was written.
568uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
569 DeclContext *DC) {
570 if (DC->getPrimaryContext() != DC)
571 return 0;
572
573 // Force the DeclContext to build a its name-lookup table.
574 DC->lookup(Context, DeclarationName());
575
576 // Serialize the contents of the mapping used for lookup. Note that,
577 // although we have two very different code paths, the serialized
578 // representation is the same for both cases: a declaration name,
579 // followed by a size, followed by references to the visible
580 // declarations that have that name.
581 uint64_t Offset = S.GetCurrentBitNo();
582 RecordData Record;
583 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
584 for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
585 D != DEnd; ++D) {
586 AddDeclarationName(D->first, Record);
587 DeclContext::lookup_result Result = D->second.getLookupResult(Context);
588 Record.push_back(Result.second - Result.first);
589 for(; Result.first != Result.second; ++Result.first)
590 AddDeclRef(*Result.first, Record);
591 }
592
593 if (Record.size() == 0)
594 return 0;
595
596 S.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record);
597 return Offset;
598}
599
600/// \brief Write a block containing all of the declarations.
601void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
602 // Enter the declarations block
603 S.EnterSubblock(pch::DECLS_BLOCK_ID, 2);
604
605 // Emit all of the declarations.
606 RecordData Record;
607 PCHDeclWriter W(*this, Record);
608 while (!DeclsToEmit.empty()) {
609 // Pull the next declaration off the queue
610 Decl *D = DeclsToEmit.front();
611 DeclsToEmit.pop();
612
613 // If this declaration is also a DeclContext, write blocks for the
614 // declarations that lexically stored inside its context and those
615 // declarations that are visible from its context. These blocks
616 // are written before the declaration itself so that we can put
617 // their offsets into the record for the declaration.
618 uint64_t LexicalOffset = 0;
619 uint64_t VisibleOffset = 0;
620 DeclContext *DC = dyn_cast<DeclContext>(D);
621 if (DC) {
622 LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
623 VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
624 }
625
626 // Determine the ID for this declaration
627 pch::ID ID = DeclIDs[D];
628 if (ID == 0)
629 ID = DeclIDs.size();
630
631 unsigned Index = ID - 1;
632
633 // Record the offset for this declaration
634 if (DeclOffsets.size() == Index)
635 DeclOffsets.push_back(S.GetCurrentBitNo());
636 else if (DeclOffsets.size() < Index) {
637 DeclOffsets.resize(Index+1);
638 DeclOffsets[Index] = S.GetCurrentBitNo();
639 }
640
641 // Build and emit a record for this declaration
642 Record.clear();
643 W.Code = (pch::DeclCode)0;
644 W.Visit(D);
645 if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
646 assert(W.Code && "Visitor did not set record code");
647 S.EmitRecord(W.Code, Record);
648 }
649
650 // Exit the declarations block
651 S.ExitBlock();
652
653 // Write the declaration offsets block
654 S.EnterSubblock(pch::DECL_OFFSETS_BLOCK_ID, 2);
655 S.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
656 S.ExitBlock();
657}
658
659PCHWriter::PCHWriter(llvm::BitstreamWriter &S)
660 : S(S), NextTypeID(pch::NUM_PREDEF_TYPE_IDS) { }
661
662void PCHWriter::WritePCH(ASTContext &Context) {
663 // Emit the file header.
664 S.Emit((unsigned)'C', 8);
665 S.Emit((unsigned)'P', 8);
666 S.Emit((unsigned)'C', 8);
667 S.Emit((unsigned)'H', 8);
668
669 // The translation unit is the first declaration we'll emit.
670 DeclIDs[Context.getTranslationUnitDecl()] = 1;
671 DeclsToEmit.push(Context.getTranslationUnitDecl());
672
673 // Write the remaining PCH contents.
674 S.EnterSubblock(pch::PCH_BLOCK_ID, 2);
Douglas Gregorab1cef72009-04-10 03:52:48 +0000675 WriteSourceManagerBlock(Context.getSourceManager());
Douglas Gregorc34897d2009-04-09 22:27:44 +0000676 WriteTypesBlock(Context);
677 WriteDeclsBlock(Context);
678 S.ExitBlock();
679}
680
681void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
682 Record.push_back(Loc.getRawEncoding());
683}
684
685void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
686 Record.push_back(Value.getBitWidth());
687 unsigned N = Value.getNumWords();
688 const uint64_t* Words = Value.getRawData();
689 for (unsigned I = 0; I != N; ++I)
690 Record.push_back(Words[I]);
691}
692
693void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
694 // FIXME: Emit an identifier ID, not the actual string!
695 const char *Name = II->getName();
696 unsigned Len = strlen(Name);
697 Record.push_back(Len);
698 Record.insert(Record.end(), Name, Name + Len);
699}
700
701void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
702 if (T.isNull()) {
703 Record.push_back(pch::PREDEF_TYPE_NULL_ID);
704 return;
705 }
706
707 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
708 pch::ID ID;
709 switch (BT->getKind()) {
710 case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break;
711 case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break;
712 case BuiltinType::Char_U: ID = pch::PREDEF_TYPE_CHAR_U_ID; break;
713 case BuiltinType::UChar: ID = pch::PREDEF_TYPE_UCHAR_ID; break;
714 case BuiltinType::UShort: ID = pch::PREDEF_TYPE_USHORT_ID; break;
715 case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break;
716 case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break;
717 case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break;
718 case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break;
719 case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break;
720 case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break;
721 case BuiltinType::Short: ID = pch::PREDEF_TYPE_SHORT_ID; break;
722 case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break;
723 case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break;
724 case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break;
725 case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break;
726 case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break;
727 case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
728 case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break;
729 case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
730 }
731
732 Record.push_back((ID << 3) | T.getCVRQualifiers());
733 return;
734 }
735
736 pch::ID &ID = TypeIDs[T.getTypePtr()];
737 if (ID == 0) // we haven't seen this type before
738 ID = NextTypeID++;
739
740 // Encode the type qualifiers in the type reference.
741 Record.push_back((ID << 3) | T.getCVRQualifiers());
742}
743
744void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
745 if (D == 0) {
746 Record.push_back(0);
747 return;
748 }
749
750 pch::ID &ID = DeclIDs[D];
751 if (ID == 0) {
752 // We haven't seen this declaration before. Give it a new ID and
753 // enqueue it in the list of declarations to emit.
754 ID = DeclIDs.size();
755 DeclsToEmit.push(const_cast<Decl *>(D));
756 }
757
758 Record.push_back(ID);
759}
760
761void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
762 Record.push_back(Name.getNameKind());
763 switch (Name.getNameKind()) {
764 case DeclarationName::Identifier:
765 AddIdentifierRef(Name.getAsIdentifierInfo(), Record);
766 break;
767
768 case DeclarationName::ObjCZeroArgSelector:
769 case DeclarationName::ObjCOneArgSelector:
770 case DeclarationName::ObjCMultiArgSelector:
771 assert(false && "Serialization of Objective-C selectors unavailable");
772 break;
773
774 case DeclarationName::CXXConstructorName:
775 case DeclarationName::CXXDestructorName:
776 case DeclarationName::CXXConversionFunctionName:
777 AddTypeRef(Name.getCXXNameType(), Record);
778 break;
779
780 case DeclarationName::CXXOperatorName:
781 Record.push_back(Name.getCXXOverloadedOperator());
782 break;
783
784 case DeclarationName::CXXUsingDirective:
785 // No extra data to emit
786 break;
787 }
788}