 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
74.3% |
298 / 401 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
98.0% |
393 / 401 |
| |
|
Line Coverage: |
87.9% |
1182 / 1344 |
| |
 |
|
 |
1 : //===--- 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 "../Sema/Sema.h" // FIXME: move header into include/clang/Sema
16 : #include "../Sema/IdentifierResolver.h" // FIXME: move header
17 : #include "clang/AST/ASTContext.h"
18 : #include "clang/AST/Decl.h"
19 : #include "clang/AST/DeclContextInternals.h"
20 : #include "clang/AST/Expr.h"
21 : #include "clang/AST/Type.h"
22 : #include "clang/AST/TypeLocVisitor.h"
23 : #include "clang/Lex/MacroInfo.h"
24 : #include "clang/Lex/Preprocessor.h"
25 : #include "clang/Lex/HeaderSearch.h"
26 : #include "clang/Basic/FileManager.h"
27 : #include "clang/Basic/OnDiskHashTable.h"
28 : #include "clang/Basic/SourceManager.h"
29 : #include "clang/Basic/SourceManagerInternals.h"
30 : #include "clang/Basic/TargetInfo.h"
31 : #include "clang/Basic/Version.h"
32 : #include "llvm/ADT/APFloat.h"
33 : #include "llvm/ADT/APInt.h"
34 : #include "llvm/ADT/StringExtras.h"
35 : #include "llvm/Bitcode/BitstreamWriter.h"
36 : #include "llvm/Support/MemoryBuffer.h"
37 : #include "llvm/System/Path.h"
38 : #include <cstdio>
39 : using namespace clang;
40 :
41 : //===----------------------------------------------------------------------===//
42 : // Type serialization
43 : //===----------------------------------------------------------------------===//
44 :
45 : namespace {
46 : class PCHTypeWriter {
47 : PCHWriter &Writer;
48 : PCHWriter::RecordData &Record;
49 :
50 : public:
51 : /// \brief Type code that corresponds to the record generated.
52 : pch::TypeCode Code;
53 :
54 373: PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
55 373: : Writer(Writer), Record(Record), Code(pch::TYPE_EXT_QUAL) { }
56 :
57 : void VisitArrayType(const ArrayType *T);
58 : void VisitFunctionType(const FunctionType *T);
59 : void VisitTagType(const TagType *T);
60 :
61 : #define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
62 : #define ABSTRACT_TYPE(Class, Base)
63 : #define DEPENDENT_TYPE(Class, Base)
64 : #include "clang/AST/TypeNodes.def"
65 : };
66 : }
67 :
68 0: void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
69 0: assert(false && "Built-in types are never serialized");
70 : }
71 :
72 2: void PCHTypeWriter::VisitComplexType(const ComplexType *T) {
73 2: Writer.AddTypeRef(T->getElementType(), Record);
74 2: Code = pch::TYPE_COMPLEX;
75 2: }
76 :
77 100: void PCHTypeWriter::VisitPointerType(const PointerType *T) {
78 100: Writer.AddTypeRef(T->getPointeeType(), Record);
79 100: Code = pch::TYPE_POINTER;
80 100: }
81 :
82 2: void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
83 2: Writer.AddTypeRef(T->getPointeeType(), Record);
84 2: Code = pch::TYPE_BLOCK_POINTER;
85 2: }
86 :
87 8: void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
88 8: Writer.AddTypeRef(T->getPointeeType(), Record);
89 8: Code = pch::TYPE_LVALUE_REFERENCE;
90 8: }
91 :
92 0: void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
93 0: Writer.AddTypeRef(T->getPointeeType(), Record);
94 0: Code = pch::TYPE_RVALUE_REFERENCE;
95 0: }
96 :
97 0: void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
98 0: Writer.AddTypeRef(T->getPointeeType(), Record);
99 0: Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
100 0: Code = pch::TYPE_MEMBER_POINTER;
101 0: }
102 :
103 31: void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
104 31: Writer.AddTypeRef(T->getElementType(), Record);
105 31: Record.push_back(T->getSizeModifier()); // FIXME: stable values
106 31: Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values
107 31: }
108 :
109 24: void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
110 24: VisitArrayType(T);
111 24: Writer.AddAPInt(T->getSize(), Record);
112 24: Code = pch::TYPE_CONSTANT_ARRAY;
113 24: }
114 :
115 6: void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
116 6: VisitArrayType(T);
117 6: Code = pch::TYPE_INCOMPLETE_ARRAY;
118 6: }
119 :
120 1: void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
121 1: VisitArrayType(T);
122 1: Writer.AddSourceLocation(T->getLBracketLoc(), Record);
123 1: Writer.AddSourceLocation(T->getRBracketLoc(), Record);
124 1: Writer.AddStmt(T->getSizeExpr());
125 1: Code = pch::TYPE_VARIABLE_ARRAY;
126 1: }
127 :
128 5: void PCHTypeWriter::VisitVectorType(const VectorType *T) {
129 5: Writer.AddTypeRef(T->getElementType(), Record);
130 5: Record.push_back(T->getNumElements());
131 5: Record.push_back(T->isAltiVec());
132 5: Record.push_back(T->isPixel());
133 5: Code = pch::TYPE_VECTOR;
134 5: }
135 :
136 4: void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
137 4: VisitVectorType(T);
138 4: Code = pch::TYPE_EXT_VECTOR;
139 4: }
140 :
141 53: void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
142 53: Writer.AddTypeRef(T->getResultType(), Record);
143 53: Record.push_back(T->getNoReturnAttr());
144 : // FIXME: need to stabilize encoding of calling convention...
145 53: Record.push_back(T->getCallConv());
146 53: }
147 :
148 6: void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
149 6: VisitFunctionType(T);
150 6: Code = pch::TYPE_FUNCTION_NO_PROTO;
151 6: }
152 :
153 47: void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
154 47: VisitFunctionType(T);
155 47: Record.push_back(T->getNumArgs());
62: branch 1 taken
47: branch 2 taken
156 109: for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
157 62: Writer.AddTypeRef(T->getArgType(I), Record);
158 47: Record.push_back(T->isVariadic());
159 47: Record.push_back(T->getTypeQuals());
160 47: Record.push_back(T->hasExceptionSpec());
161 47: Record.push_back(T->hasAnyExceptionSpec());
162 47: Record.push_back(T->getNumExceptions());
0: branch 1 not taken
47: branch 2 taken
163 47: for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
164 0: Writer.AddTypeRef(T->getExceptionType(I), Record);
165 47: Code = pch::TYPE_FUNCTION_PROTO;
166 47: }
167 :
168 : #if 0
169 : // For when we want it....
170 : void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
171 : Writer.AddDeclRef(T->getDecl(), Record);
172 : Code = pch::TYPE_UNRESOLVED_USING;
173 : }
174 : #endif
175 :
176 42: void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
177 42: Writer.AddDeclRef(T->getDecl(), Record);
178 42: Code = pch::TYPE_TYPEDEF;
179 42: }
180 :
181 39: void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
182 39: Writer.AddStmt(T->getUnderlyingExpr());
183 39: Code = pch::TYPE_TYPEOF_EXPR;
184 39: }
185 :
186 4: void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) {
187 4: Writer.AddTypeRef(T->getUnderlyingType(), Record);
188 4: Code = pch::TYPE_TYPEOF;
189 4: }
190 :
191 0: void PCHTypeWriter::VisitDecltypeType(const DecltypeType *T) {
192 0: Writer.AddStmt(T->getUnderlyingExpr());
193 0: Code = pch::TYPE_DECLTYPE;
194 0: }
195 :
196 30: void PCHTypeWriter::VisitTagType(const TagType *T) {
197 30: Writer.AddDeclRef(T->getDecl(), Record);
198 : assert(!T->isBeingDefined() &&
30: branch 1 taken
0: branch 2 not taken
199 30: "Cannot serialize in the middle of a type definition");
200 30: }
201 :
202 25: void PCHTypeWriter::VisitRecordType(const RecordType *T) {
203 25: VisitTagType(T);
204 25: Code = pch::TYPE_RECORD;
205 25: }
206 :
207 5: void PCHTypeWriter::VisitEnumType(const EnumType *T) {
208 5: VisitTagType(T);
209 5: Code = pch::TYPE_ENUM;
210 5: }
211 :
212 0: void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
213 0: Writer.AddTypeRef(T->getUnderlyingType(), Record);
214 0: Record.push_back(T->getTagKind());
215 0: Code = pch::TYPE_ELABORATED;
216 0: }
217 :
218 : void
219 : PCHTypeWriter::VisitSubstTemplateTypeParmType(
220 0: const SubstTemplateTypeParmType *T) {
221 0: Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
222 0: Writer.AddTypeRef(T->getReplacementType(), Record);
223 0: Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM;
224 0: }
225 :
226 : void
227 : PCHTypeWriter::VisitTemplateSpecializationType(
228 0: const TemplateSpecializationType *T) {
229 : // FIXME: Serialize this type (C++ only)
230 0: assert(false && "Cannot serialize template specialization types");
231 : }
232 :
233 0: void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) {
234 : // FIXME: Serialize this type (C++ only)
235 0: assert(false && "Cannot serialize qualified name types");
236 : }
237 :
238 20: void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
239 20: Writer.AddDeclRef(T->getDecl(), Record);
240 20: Record.push_back(T->getNumProtocols());
1: branch 1 taken
20: branch 2 taken
241 41: for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
242 20: E = T->qual_end(); I != E; ++I)
243 1: Writer.AddDeclRef(*I, Record);
244 20: Code = pch::TYPE_OBJC_INTERFACE;
245 20: }
246 :
247 : void
248 36: PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
249 36: Writer.AddTypeRef(T->getPointeeType(), Record);
250 36: Record.push_back(T->getNumProtocols());
6: branch 1 taken
36: branch 2 taken
251 78: for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
252 36: E = T->qual_end(); I != E; ++I)
253 6: Writer.AddDeclRef(*I, Record);
254 36: Code = pch::TYPE_OBJC_OBJECT_POINTER;
255 36: }
256 :
257 : namespace {
258 :
259 : class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
260 : PCHWriter &Writer;
261 : PCHWriter::RecordData &Record;
262 :
263 : public:
264 420: TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
265 420: : Writer(Writer), Record(Record) { }
266 :
267 : #define ABSTRACT_TYPELOC(CLASS, PARENT)
268 : #define TYPELOC(CLASS, PARENT) \
269 : void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
270 : #include "clang/AST/TypeLocNodes.def"
271 :
272 : void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);
273 : void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
274 : };
275 :
276 : }
277 :
278 16: void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
279 : // nothing to do
280 16: }
281 321: void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
282 321: Writer.AddSourceLocation(TL.getBuiltinLoc(), Record);
187: branch 1 taken
134: branch 2 taken
283 321: if (TL.needsExtraLocalData()) {
284 187: Record.push_back(TL.getWrittenTypeSpec());
285 187: Record.push_back(TL.getWrittenSignSpec());
286 187: Record.push_back(TL.getWrittenWidthSpec());
287 187: Record.push_back(TL.hasModeAttr());
288 : }
289 321: }
290 1: void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
291 1: Writer.AddSourceLocation(TL.getNameLoc(), Record);
292 1: }
293 108: void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
294 108: Writer.AddSourceLocation(TL.getStarLoc(), Record);
295 108: }
296 2: void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
297 2: Writer.AddSourceLocation(TL.getCaretLoc(), Record);
298 2: }
299 2: void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
300 2: Writer.AddSourceLocation(TL.getAmpLoc(), Record);
301 2: }
302 0: void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
303 0: Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record);
304 0: }
305 0: void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
306 0: Writer.AddSourceLocation(TL.getStarLoc(), Record);
307 0: }
308 19: void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
309 19: Writer.AddSourceLocation(TL.getLBracketLoc(), Record);
310 19: Writer.AddSourceLocation(TL.getRBracketLoc(), Record);
12: branch 1 taken
7: branch 2 taken
311 19: Record.push_back(TL.getSizeExpr() ? 1 : 0);
12: branch 1 taken
7: branch 2 taken
312 19: if (TL.getSizeExpr())
313 12: Writer.AddStmt(TL.getSizeExpr());
314 19: }
315 11: void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
316 11: VisitArrayTypeLoc(TL);
317 11: }
318 7: void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
319 7: VisitArrayTypeLoc(TL);
320 7: }
321 1: void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
322 1: VisitArrayTypeLoc(TL);
323 1: }
324 : void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
325 0: DependentSizedArrayTypeLoc TL) {
326 0: VisitArrayTypeLoc(TL);
327 0: }
328 : void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
329 0: DependentSizedExtVectorTypeLoc TL) {
330 0: Writer.AddSourceLocation(TL.getNameLoc(), Record);
331 0: }
332 1: void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
333 1: Writer.AddSourceLocation(TL.getNameLoc(), Record);
334 1: }
335 4: void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
336 4: Writer.AddSourceLocation(TL.getNameLoc(), Record);
337 4: }
338 50: void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
339 50: Writer.AddSourceLocation(TL.getLParenLoc(), Record);
340 50: Writer.AddSourceLocation(TL.getRParenLoc(), Record);
57: branch 1 taken
50: branch 2 taken
341 107: for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
342 57: Writer.AddDeclRef(TL.getArg(i), Record);
343 50: }
344 44: void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
345 44: VisitFunctionTypeLoc(TL);
346 44: }
347 6: void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
348 6: VisitFunctionTypeLoc(TL);
349 6: }
350 0: void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
351 0: Writer.AddSourceLocation(TL.getNameLoc(), Record);
352 0: }
353 15: void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
354 15: Writer.AddSourceLocation(TL.getNameLoc(), Record);
355 15: }
356 39: void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
357 39: Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
358 39: Writer.AddSourceLocation(TL.getLParenLoc(), Record);
359 39: Writer.AddSourceLocation(TL.getRParenLoc(), Record);
360 39: }
361 4: void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
362 4: Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
363 4: Writer.AddSourceLocation(TL.getLParenLoc(), Record);
364 4: Writer.AddSourceLocation(TL.getRParenLoc(), Record);
365 4: Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record);
366 4: }
367 0: void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
368 0: Writer.AddSourceLocation(TL.getNameLoc(), Record);
369 0: }
370 28: void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
371 28: Writer.AddSourceLocation(TL.getNameLoc(), Record);
372 28: }
373 1: void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
374 1: Writer.AddSourceLocation(TL.getNameLoc(), Record);
375 1: }
376 0: void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
377 0: Writer.AddSourceLocation(TL.getNameLoc(), Record);
378 0: }
379 0: void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
380 0: Writer.AddSourceLocation(TL.getNameLoc(), Record);
381 0: }
382 : void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
383 0: SubstTemplateTypeParmTypeLoc TL) {
384 0: Writer.AddSourceLocation(TL.getNameLoc(), Record);
385 0: }
386 : void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
387 0: TemplateSpecializationTypeLoc TL) {
388 0: Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record);
389 0: Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
390 0: Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
0: branch 1 not taken
0: branch 2 not taken
391 0: for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
392 0: Writer.AddTemplateArgumentLoc(TL.getArgLoc(i), Record);
393 0: }
394 0: void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
395 0: Writer.AddSourceLocation(TL.getNameLoc(), Record);
396 0: }
397 0: void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
398 0: Writer.AddSourceLocation(TL.getNameLoc(), Record);
399 0: }
400 6: void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
401 6: Writer.AddSourceLocation(TL.getNameLoc(), Record);
402 6: Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
403 6: Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
1: branch 1 taken
6: branch 2 taken
404 7: for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
405 1: Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
406 6: }
407 31: void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
408 31: Writer.AddSourceLocation(TL.getStarLoc(), Record);
409 31: Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
410 31: Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
411 31: Record.push_back(TL.hasBaseTypeAsWritten());
412 31: Record.push_back(TL.hasProtocolsAsWritten());
5: branch 1 taken
26: branch 2 taken
413 31: if (TL.hasProtocolsAsWritten())
5: branch 1 taken
5: branch 2 taken
414 10: for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
415 5: Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
416 31: }
417 :
418 : //===----------------------------------------------------------------------===//
419 : // PCHWriter Implementation
420 : //===----------------------------------------------------------------------===//
421 :
422 : static void EmitBlockID(unsigned ID, const char *Name,
423 : llvm::BitstreamWriter &Stream,
424 176: PCHWriter::RecordData &Record) {
425 176: Record.clear();
426 176: Record.push_back(ID);
427 176: Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
428 :
429 : // Emit the block name if present.
176: branch 0 taken
0: branch 1 not taken
0: branch 2 not taken
176: branch 3 taken
430 176: if (Name == 0 || Name[0] == 0) return;
431 176: Record.clear();
2728: branch 0 taken
176: branch 1 taken
432 3080: while (*Name)
433 2728: Record.push_back(*Name++);
434 176: Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
435 : }
436 :
437 : static void EmitRecordID(unsigned ID, const char *Name,
438 : llvm::BitstreamWriter &Stream,
439 6776: PCHWriter::RecordData &Record) {
440 6776: Record.clear();
441 6776: Record.push_back(ID);
114444: branch 0 taken
6776: branch 1 taken
442 127996: while (*Name)
443 114444: Record.push_back(*Name++);
444 6776: Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
445 6776: }
446 :
447 : static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
448 44: PCHWriter::RecordData &Record) {
449 : #define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record)
450 44: RECORD(STMT_STOP);
451 44: RECORD(STMT_NULL_PTR);
452 44: RECORD(STMT_NULL);
453 44: RECORD(STMT_COMPOUND);
454 44: RECORD(STMT_CASE);
455 44: RECORD(STMT_DEFAULT);
456 44: RECORD(STMT_LABEL);
457 44: RECORD(STMT_IF);
458 44: RECORD(STMT_SWITCH);
459 44: RECORD(STMT_WHILE);
460 44: RECORD(STMT_DO);
461 44: RECORD(STMT_FOR);
462 44: RECORD(STMT_GOTO);
463 44: RECORD(STMT_INDIRECT_GOTO);
464 44: RECORD(STMT_CONTINUE);
465 44: RECORD(STMT_BREAK);
466 44: RECORD(STMT_RETURN);
467 44: RECORD(STMT_DECL);
468 44: RECORD(STMT_ASM);
469 44: RECORD(EXPR_PREDEFINED);
470 44: RECORD(EXPR_DECL_REF);
471 44: RECORD(EXPR_INTEGER_LITERAL);
472 44: RECORD(EXPR_FLOATING_LITERAL);
473 44: RECORD(EXPR_IMAGINARY_LITERAL);
474 44: RECORD(EXPR_STRING_LITERAL);
475 44: RECORD(EXPR_CHARACTER_LITERAL);
476 44: RECORD(EXPR_PAREN);
477 44: RECORD(EXPR_UNARY_OPERATOR);
478 44: RECORD(EXPR_SIZEOF_ALIGN_OF);
479 44: RECORD(EXPR_ARRAY_SUBSCRIPT);
480 44: RECORD(EXPR_CALL);
481 44: RECORD(EXPR_MEMBER);
482 44: RECORD(EXPR_BINARY_OPERATOR);
483 44: RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR);
484 44: RECORD(EXPR_CONDITIONAL_OPERATOR);
485 44: RECORD(EXPR_IMPLICIT_CAST);
486 44: RECORD(EXPR_CSTYLE_CAST);
487 44: RECORD(EXPR_COMPOUND_LITERAL);
488 44: RECORD(EXPR_EXT_VECTOR_ELEMENT);
489 44: RECORD(EXPR_INIT_LIST);
490 44: RECORD(EXPR_DESIGNATED_INIT);
491 44: RECORD(EXPR_IMPLICIT_VALUE_INIT);
492 44: RECORD(EXPR_VA_ARG);
493 44: RECORD(EXPR_ADDR_LABEL);
494 44: RECORD(EXPR_STMT);
495 44: RECORD(EXPR_TYPES_COMPATIBLE);
496 44: RECORD(EXPR_CHOOSE);
497 44: RECORD(EXPR_GNU_NULL);
498 44: RECORD(EXPR_SHUFFLE_VECTOR);
499 44: RECORD(EXPR_BLOCK);
500 44: RECORD(EXPR_BLOCK_DECL_REF);
501 44: RECORD(EXPR_OBJC_STRING_LITERAL);
502 44: RECORD(EXPR_OBJC_ENCODE);
503 44: RECORD(EXPR_OBJC_SELECTOR_EXPR);
504 44: RECORD(EXPR_OBJC_PROTOCOL_EXPR);
505 44: RECORD(EXPR_OBJC_IVAR_REF_EXPR);
506 44: RECORD(EXPR_OBJC_PROPERTY_REF_EXPR);
507 44: RECORD(EXPR_OBJC_KVC_REF_EXPR);
508 44: RECORD(EXPR_OBJC_MESSAGE_EXPR);
509 44: RECORD(EXPR_OBJC_SUPER_EXPR);
510 44: RECORD(STMT_OBJC_FOR_COLLECTION);
511 44: RECORD(STMT_OBJC_CATCH);
512 44: RECORD(STMT_OBJC_FINALLY);
513 44: RECORD(STMT_OBJC_AT_TRY);
514 44: RECORD(STMT_OBJC_AT_SYNCHRONIZED);
515 44: RECORD(STMT_OBJC_AT_THROW);
516 44: RECORD(EXPR_CXX_OPERATOR_CALL);
517 44: RECORD(EXPR_CXX_CONSTRUCT);
518 44: RECORD(EXPR_CXX_STATIC_CAST);
519 44: RECORD(EXPR_CXX_DYNAMIC_CAST);
520 44: RECORD(EXPR_CXX_REINTERPRET_CAST);
521 44: RECORD(EXPR_CXX_CONST_CAST);
522 44: RECORD(EXPR_CXX_FUNCTIONAL_CAST);
523 44: RECORD(EXPR_CXX_BOOL_LITERAL);
524 44: RECORD(EXPR_CXX_NULL_PTR_LITERAL);
525 : #undef RECORD
526 44: }
527 :
528 44: void PCHWriter::WriteBlockInfoBlock() {
529 44: RecordData Record;
530 44: Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3);
531 :
532 : #define BLOCK(X) EmitBlockID(pch::X ## _ID, #X, Stream, Record)
533 : #define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record)
534 :
535 : // PCH Top-Level Block.
536 44: BLOCK(PCH_BLOCK);
537 44: RECORD(ORIGINAL_FILE_NAME);
538 44: RECORD(TYPE_OFFSET);
539 44: RECORD(DECL_OFFSET);
540 44: RECORD(LANGUAGE_OPTIONS);
541 44: RECORD(METADATA);
542 44: RECORD(IDENTIFIER_OFFSET);
543 44: RECORD(IDENTIFIER_TABLE);
544 44: RECORD(EXTERNAL_DEFINITIONS);
545 44: RECORD(SPECIAL_TYPES);
546 44: RECORD(STATISTICS);
547 44: RECORD(TENTATIVE_DEFINITIONS);
548 44: RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS);
549 44: RECORD(SELECTOR_OFFSETS);
550 44: RECORD(METHOD_POOL);
551 44: RECORD(PP_COUNTER_VALUE);
552 44: RECORD(SOURCE_LOCATION_OFFSETS);
553 44: RECORD(SOURCE_LOCATION_PRELOADS);
554 44: RECORD(STAT_CACHE);
555 44: RECORD(EXT_VECTOR_DECLS);
556 44: RECORD(COMMENT_RANGES);
557 44: RECORD(VERSION_CONTROL_BRANCH_REVISION);
558 :
559 : // SourceManager Block.
560 44: BLOCK(SOURCE_MANAGER_BLOCK);
561 44: RECORD(SM_SLOC_FILE_ENTRY);
562 44: RECORD(SM_SLOC_BUFFER_ENTRY);
563 44: RECORD(SM_SLOC_BUFFER_BLOB);
564 44: RECORD(SM_SLOC_INSTANTIATION_ENTRY);
565 44: RECORD(SM_LINE_TABLE);
566 44: RECORD(SM_HEADER_FILE_INFO);
567 :
568 : // Preprocessor Block.
569 44: BLOCK(PREPROCESSOR_BLOCK);
570 44: RECORD(PP_MACRO_OBJECT_LIKE);
571 44: RECORD(PP_MACRO_FUNCTION_LIKE);
572 44: RECORD(PP_TOKEN);
573 :
574 : // Decls and Types block.
575 44: BLOCK(DECLTYPES_BLOCK);
576 44: RECORD(TYPE_EXT_QUAL);
577 44: RECORD(TYPE_COMPLEX);
578 44: RECORD(TYPE_POINTER);
579 44: RECORD(TYPE_BLOCK_POINTER);
580 44: RECORD(TYPE_LVALUE_REFERENCE);
581 44: RECORD(TYPE_RVALUE_REFERENCE);
582 44: RECORD(TYPE_MEMBER_POINTER);
583 44: RECORD(TYPE_CONSTANT_ARRAY);
584 44: RECORD(TYPE_INCOMPLETE_ARRAY);
585 44: RECORD(TYPE_VARIABLE_ARRAY);
586 44: RECORD(TYPE_VECTOR);
587 44: RECORD(TYPE_EXT_VECTOR);
588 44: RECORD(TYPE_FUNCTION_PROTO);
589 44: RECORD(TYPE_FUNCTION_NO_PROTO);
590 44: RECORD(TYPE_TYPEDEF);
591 44: RECORD(TYPE_TYPEOF_EXPR);
592 44: RECORD(TYPE_TYPEOF);
593 44: RECORD(TYPE_RECORD);
594 44: RECORD(TYPE_ENUM);
595 44: RECORD(TYPE_OBJC_INTERFACE);
596 44: RECORD(TYPE_OBJC_OBJECT_POINTER);
597 44: RECORD(DECL_ATTR);
598 44: RECORD(DECL_TRANSLATION_UNIT);
599 44: RECORD(DECL_TYPEDEF);
600 44: RECORD(DECL_ENUM);
601 44: RECORD(DECL_RECORD);
602 44: RECORD(DECL_ENUM_CONSTANT);
603 44: RECORD(DECL_FUNCTION);
604 44: RECORD(DECL_OBJC_METHOD);
605 44: RECORD(DECL_OBJC_INTERFACE);
606 44: RECORD(DECL_OBJC_PROTOCOL);
607 44: RECORD(DECL_OBJC_IVAR);
608 44: RECORD(DECL_OBJC_AT_DEFS_FIELD);
609 44: RECORD(DECL_OBJC_CLASS);
610 44: RECORD(DECL_OBJC_FORWARD_PROTOCOL);
611 44: RECORD(DECL_OBJC_CATEGORY);
612 44: RECORD(DECL_OBJC_CATEGORY_IMPL);
613 44: RECORD(DECL_OBJC_IMPLEMENTATION);
614 44: RECORD(DECL_OBJC_COMPATIBLE_ALIAS);
615 44: RECORD(DECL_OBJC_PROPERTY);
616 44: RECORD(DECL_OBJC_PROPERTY_IMPL);
617 44: RECORD(DECL_FIELD);
618 44: RECORD(DECL_VAR);
619 44: RECORD(DECL_IMPLICIT_PARAM);
620 44: RECORD(DECL_PARM_VAR);
621 44: RECORD(DECL_FILE_SCOPE_ASM);
622 44: RECORD(DECL_BLOCK);
623 44: RECORD(DECL_CONTEXT_LEXICAL);
624 44: RECORD(DECL_CONTEXT_VISIBLE);
625 : // Statements and Exprs can occur in the Decls and Types block.
626 44: AddStmtsExprs(Stream, Record);
627 : #undef RECORD
628 : #undef BLOCK
629 44: Stream.ExitBlock();
630 44: }
631 :
632 : /// \brief Adjusts the given filename to only write out the portion of the
633 : /// filename that is not part of the system root directory.
634 : ///
635 : /// \param Filename the file name to adjust.
636 : ///
637 : /// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and
638 : /// the returned filename will be adjusted by this system root.
639 : ///
640 : /// \returns either the original filename (if it needs no adjustment) or the
641 : /// adjusted filename (which points into the @p Filename parameter).
642 : static const char *
643 268: adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) {
0: branch 0 not taken
268: branch 1 taken
644 268: assert(Filename && "No file name to adjust?");
645 :
262: branch 0 taken
6: branch 1 taken
646 268: if (!isysroot)
647 262: return Filename;
648 :
649 : // Verify that the filename and the system root have the same prefix.
650 6: unsigned Pos = 0;
194: branch 0 taken
0: branch 1 not taken
191: branch 2 taken
3: branch 3 taken
651 194: for (; Filename[Pos] && isysroot[Pos]; ++Pos)
3: branch 0 taken
188: branch 1 taken
652 191: if (Filename[Pos] != isysroot[Pos])
653 3: return Filename; // Prefixes don't match.
654 :
655 : // We hit the end of the filename before we hit the end of the system root.
0: branch 0 not taken
3: branch 1 taken
656 3: if (!Filename[Pos])
657 0: return Filename;
658 :
659 : // If the file name has a '/' at the current position, skip over the '/'.
660 : // We distinguish sysroot-based includes from absolute includes by the
661 : // absence of '/' at the beginning of sysroot-based includes.
3: branch 0 taken
0: branch 1 not taken
662 3: if (Filename[Pos] == '/')
663 3: ++Pos;
664 :
665 3: return Filename + Pos;
666 : }
667 :
668 : /// \brief Write the PCH metadata (e.g., i686-apple-darwin9).
669 44: void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
670 : using namespace llvm;
671 :
672 : // Metadata
673 44: const TargetInfo &Target = Context.Target;
674 44: BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev();
675 44: MetaAbbrev->Add(BitCodeAbbrevOp(pch::METADATA));
676 44: MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major
677 44: MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor
678 44: MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major
679 44: MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor
680 44: MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
681 44: MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple
682 44: unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
683 :
684 44: RecordData Record;
685 44: Record.push_back(pch::METADATA);
686 44: Record.push_back(pch::VERSION_MAJOR);
687 44: Record.push_back(pch::VERSION_MINOR);
688 44: Record.push_back(CLANG_VERSION_MAJOR);
689 44: Record.push_back(CLANG_VERSION_MINOR);
690 44: Record.push_back(isysroot != 0);
691 44: const std::string &TripleStr = Target.getTriple().getTriple();
692 44: Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, TripleStr);
693 :
694 : // Original file name
695 44: SourceManager &SM = Context.getSourceManager();
44: branch 2 taken
0: branch 3 not taken
696 44: if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
697 44: BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev();
698 44: FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME));
699 44: FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
700 44: unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);
701 :
702 44: llvm::sys::Path MainFilePath(MainFile->getName());
703 44: std::string MainFileName;
704 :
0: branch 1 not taken
44: branch 2 taken
705 44: if (!MainFilePath.isAbsolute()) {
706 0: llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
707 0: P.appendComponent(MainFilePath.str());
708 0: MainFileName = P.str();
709 : } else {
710 44: MainFileName = MainFilePath.str();
711 : }
712 :
713 44: const char *MainFileNameStr = MainFileName.c_str();
714 : MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr,
715 44: isysroot);
716 44: RecordData Record;
717 44: Record.push_back(pch::ORIGINAL_FILE_NAME);
718 44: Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
719 : }
720 :
721 : // Repository branch/version information.
722 44: BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev();
723 44: RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION));
724 44: RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
725 44: unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev);
726 44: Record.clear();
727 44: Record.push_back(pch::VERSION_CONTROL_BRANCH_REVISION);
728 : Stream.EmitRecordWithBlob(RepoAbbrevCode, Record,
729 44: getClangFullRepositoryVersion());
730 44: }
731 :
732 : /// \brief Write the LangOptions structure.
733 44: void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
734 44: RecordData Record;
735 44: Record.push_back(LangOpts.Trigraphs);
736 44: Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments.
737 44: Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers.
738 44: Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode.
739 44: Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc)
740 44: Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'.
741 44: Record.push_back(LangOpts.Digraphs); // C94, C99 and C++
742 44: Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants.
743 44: Record.push_back(LangOpts.C99); // C99 Support
744 44: Record.push_back(LangOpts.Microsoft); // Microsoft extensions.
745 44: Record.push_back(LangOpts.CPlusPlus); // C++ Support
746 44: Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support
747 44: Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords.
748 :
749 44: Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled.
750 44: Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled.
751 44: Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C
752 : // modern abi enabled.
753 44: Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced
754 : // modern abi enabled.
755 :
756 44: Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings
757 44: Record.push_back(LangOpts.WritableStrings); // Allow writable strings
758 44: Record.push_back(LangOpts.LaxVectorConversions);
759 44: Record.push_back(LangOpts.AltiVec);
760 44: Record.push_back(LangOpts.Exceptions); // Support exception handling.
761 :
762 44: Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime.
763 44: Record.push_back(LangOpts.Freestanding); // Freestanding implementation
764 44: Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin)
765 :
766 : // Whether static initializers are protected by locks.
767 44: Record.push_back(LangOpts.ThreadsafeStatics);
768 44: Record.push_back(LangOpts.POSIXThreads);
769 44: Record.push_back(LangOpts.Blocks); // block extension to C
770 44: Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if
771 : // they are unused.
772 44: Record.push_back(LangOpts.MathErrno); // Math functions must respect errno
773 : // (modulo the platform support).
774 :
775 44: Record.push_back(LangOpts.OverflowChecking); // Extension to call a handler function when
776 : // signed integer arithmetic overflows.
777 :
778 44: Record.push_back(LangOpts.HeinousExtensions); // Extensions that we really don't like and
779 : // may be ripped out at any time.
780 :
781 44: Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined.
782 44: Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be
783 : // defined.
784 44: Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as
785 : // opposed to __DYNAMIC__).
786 44: Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero.
787 :
788 44: Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be
789 : // used (instead of C99 semantics).
790 44: Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined.
791 44: Record.push_back(LangOpts.AccessControl); // Whether C++ access control should
792 : // be enabled.
793 44: Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or
794 : // unsigned type
795 44: Record.push_back(LangOpts.ShortWChar); // force wchar_t to be unsigned short
796 44: Record.push_back(LangOpts.getGCMode());
797 44: Record.push_back(LangOpts.getVisibilityMode());
798 44: Record.push_back(LangOpts.getStackProtectorMode());
799 44: Record.push_back(LangOpts.InstantiationDepth);
800 44: Record.push_back(LangOpts.OpenCL);
801 44: Record.push_back(LangOpts.CatchUndefined);
802 44: Record.push_back(LangOpts.ElideConstructors);
803 44: Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record);
804 44: }
805 :
806 : //===----------------------------------------------------------------------===//
807 : // stat cache Serialization
808 : //===----------------------------------------------------------------------===//
809 :
810 : namespace {
811 : // Trait used for the on-disk hash table of stat cache results.
812 : class PCHStatCacheTrait {
813 : public:
814 : typedef const char * key_type;
815 : typedef key_type key_type_ref;
816 :
817 : typedef std::pair<int, struct stat> data_type;
818 : typedef const data_type& data_type_ref;
819 :
820 87: static unsigned ComputeHash(const char *path) {
821 87: return llvm::HashString(path);
822 : }
823 :
824 : std::pair<unsigned,unsigned>
825 : EmitKeyDataLength(llvm::raw_ostream& Out, const char *path,
826 87: data_type_ref Data) {
827 87: unsigned StrLen = strlen(path);
828 87: clang::io::Emit16(Out, StrLen);
829 87: unsigned DataLen = 1; // result value
87: branch 0 taken
0: branch 1 not taken
830 87: if (Data.first == 0)
831 87: DataLen += 4 + 4 + 2 + 8 + 8;
832 87: clang::io::Emit8(Out, DataLen);
833 87: return std::make_pair(StrLen + 1, DataLen);
834 : }
835 :
836 87: void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) {
837 87: Out.write(path, KeyLen);
838 87: }
839 :
840 : void EmitData(llvm::raw_ostream& Out, key_type_ref,
841 87: data_type_ref Data, unsigned DataLen) {
842 : using namespace clang::io;
843 87: uint64_t Start = Out.tell(); (void)Start;
844 :
845 : // Result of stat()
0: branch 0 not taken
87: branch 1 taken
846 87: Emit8(Out, Data.first? 1 : 0);
847 :
87: branch 0 taken
0: branch 1 not taken
848 87: if (Data.first == 0) {
849 87: Emit32(Out, (uint32_t) Data.second.st_ino);
850 87: Emit32(Out, (uint32_t) Data.second.st_dev);
851 87: Emit16(Out, (uint16_t) Data.second.st_mode);
852 87: Emit64(Out, (uint64_t) Data.second.st_mtime);
853 87: Emit64(Out, (uint64_t) Data.second.st_size);
854 : }
855 :
87: branch 1 taken
0: branch 2 not taken
856 87: assert(Out.tell() - Start == DataLen && "Wrong data length");
857 87: }
858 : };
859 : } // end anonymous namespace
860 :
861 : /// \brief Write the stat() system call cache to the PCH file.
862 : void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls,
863 43: const char *isysroot) {
864 : // Build the on-disk hash table containing information about every
865 : // stat() call.
866 43: OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator;
867 43: unsigned NumStatEntries = 0;
87: branch 3 taken
43: branch 4 taken
868 173: for (MemorizeStatCalls::iterator Stat = StatCalls.begin(),
869 43: StatEnd = StatCalls.end();
870 : Stat != StatEnd; ++Stat, ++NumStatEntries) {
871 87: const char *Filename = Stat->first();
872 87: Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
873 87: Generator.insert(Filename, Stat->second);
874 : }
875 :
876 : // Create the on-disk hash table in a buffer.
877 43: llvm::SmallString<4096> StatCacheData;
878 : uint32_t BucketOffset;
879 : {
880 43: llvm::raw_svector_ostream Out(StatCacheData);
881 : // Make sure that no bucket is at offset 0
882 43: clang::io::Emit32(Out, 0);
883 43: BucketOffset = Generator.Emit(Out);
884 : }
885 :
886 : // Create a blob abbreviation
887 : using namespace llvm;
888 43: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
889 43: Abbrev->Add(BitCodeAbbrevOp(pch::STAT_CACHE));
890 43: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
891 43: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
892 43: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
893 43: unsigned StatCacheAbbrev = Stream.EmitAbbrev(Abbrev);
894 :
895 : // Write the stat cache
896 43: RecordData Record;
897 43: Record.push_back(pch::STAT_CACHE);
898 43: Record.push_back(BucketOffset);
899 43: Record.push_back(NumStatEntries);
900 43: Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str());
901 43: }
902 :
903 : //===----------------------------------------------------------------------===//
904 : // Source Manager Serialization
905 : //===----------------------------------------------------------------------===//
906 :
907 : /// \brief Create an abbreviation for the SLocEntry that refers to a
908 : /// file.
909 44: static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
910 : using namespace llvm;
911 44: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
912 44: Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
913 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
914 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
915 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
916 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
917 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
918 44: return Stream.EmitAbbrev(Abbrev);
919 : }
920 :
921 : /// \brief Create an abbreviation for the SLocEntry that refers to a
922 : /// buffer.
923 44: static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
924 : using namespace llvm;
925 44: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
926 44: Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
927 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
928 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
929 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
930 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
931 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
932 44: return Stream.EmitAbbrev(Abbrev);
933 : }
934 :
935 : /// \brief Create an abbreviation for the SLocEntry that refers to a
936 : /// buffer's blob.
937 44: static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
938 : using namespace llvm;
939 44: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
940 44: Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
941 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
942 44: return Stream.EmitAbbrev(Abbrev);
943 : }
944 :
945 : /// \brief Create an abbreviation for the SLocEntry that refers to an
946 : /// buffer.
947 44: static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) {
948 : using namespace llvm;
949 44: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
950 44: Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
951 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
952 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
953 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
954 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
955 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
956 44: return Stream.EmitAbbrev(Abbrev);
957 : }
958 :
959 : /// \brief Writes the block containing the serialized form of the
960 : /// source manager.
961 : ///
962 : /// TODO: We should probably use an on-disk hash table (stored in a
963 : /// blob), indexed based on the file name, so that we only create
964 : /// entries for files that we actually need. In the common case (no
965 : /// errors), we probably won't have to create file entries for any of
966 : /// the files in the AST.
967 : void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
968 : const Preprocessor &PP,
969 44: const char *isysroot) {
970 44: RecordData Record;
971 :
972 : // Enter the source manager block.
973 44: Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
974 :
975 : // Abbreviations for the various kinds of source-location entries.
976 44: unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream);
977 44: unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream);
978 44: unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream);
979 44: unsigned SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream);
980 :
981 : // Write the line table.
44: branch 1 taken
0: branch 2 not taken
982 44: if (SourceMgr.hasLineTable()) {
983 44: LineTableInfo &LineTable = SourceMgr.getLineTable();
984 :
985 : // Emit the file names
986 44: Record.push_back(LineTable.getNumFilenames());
89: branch 1 taken
44: branch 2 taken
987 133: for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
988 : // Emit the file name
989 89: const char *Filename = LineTable.getFilename(I);
990 89: Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
89: branch 0 taken
0: branch 1 not taken
991 89: unsigned FilenameLen = Filename? strlen(Filename) : 0;
992 89: Record.push_back(FilenameLen);
89: branch 0 taken
0: branch 1 not taken
993 89: if (FilenameLen)
994 89: Record.insert(Record.end(), Filename, Filename + FilenameLen);
995 : }
996 :
997 : // Emit the line entries
45: branch 4 taken
44: branch 5 taken
998 89: for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
999 : L != LEnd; ++L) {
1000 : // Emit the file ID
1001 45: Record.push_back(L->first);
1002 :
1003 : // Emit the line entries
1004 45: Record.push_back(L->second.size());
133: branch 4 taken
45: branch 5 taken
1005 223: for (std::vector<LineEntry>::iterator LE = L->second.begin(),
1006 45: LEEnd = L->second.end();
1007 : LE != LEEnd; ++LE) {
1008 133: Record.push_back(LE->FileOffset);
1009 133: Record.push_back(LE->LineNo);
1010 133: Record.push_back(LE->FilenameID);
1011 133: Record.push_back((unsigned)LE->FileKind);
1012 133: Record.push_back(LE->IncludeOffset);
1013 : }
1014 : }
1015 44: Stream.EmitRecord(pch::SM_LINE_TABLE, Record);
1016 : }
1017 :
1018 : // Write out entries for all of the header files we know about.
1019 44: HeaderSearch &HS = PP.getHeaderSearchInfo();
1020 44: Record.clear();
49: branch 3 taken
44: branch 4 taken
1021 137: for (HeaderSearch::header_file_iterator I = HS.header_file_begin(),
1022 44: E = HS.header_file_end();
1023 : I != E; ++I) {
1024 49: Record.push_back(I->isImport);
1025 49: Record.push_back(I->DirInfo);
1026 49: Record.push_back(I->NumIncludes);
1027 49: AddIdentifierRef(I->ControllingMacro, Record);
1028 49: Stream.EmitRecord(pch::SM_HEADER_FILE_INFO, Record);
1029 49: Record.clear();
1030 : }
1031 :
1032 : // Write out the source location entry table. We skip the first
1033 : // entry, which is always the same dummy entry.
1034 44: std::vector<uint32_t> SLocEntryOffsets;
1035 44: RecordData PreloadSLocs;
1036 44: SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1);
189: branch 1 taken
44: branch 2 taken
1037 233: for (unsigned I = 1, N = SourceMgr.sloc_entry_size(); I != N; ++I) {
1038 : // Get this source location entry.
1039 189: const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
1040 :
1041 : // Record the offset of this source-location entry.
1042 189: SLocEntryOffsets.push_back(Stream.GetCurrentBitNo());
1043 :
1044 : // Figure out which record code to use.
1045 : unsigned Code;
95: branch 1 taken
94: branch 2 taken
1046 189: if (SLoc->isFile()) {
48: branch 2 taken
47: branch 3 taken
1047 95: if (SLoc->getFile().getContentCache()->Entry)
1048 48: Code = pch::SM_SLOC_FILE_ENTRY;
1049 : else
1050 47: Code = pch::SM_SLOC_BUFFER_ENTRY;
1051 : } else
1052 94: Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
1053 189: Record.clear();
1054 189: Record.push_back(Code);
1055 :
1056 189: Record.push_back(SLoc->getOffset());
95: branch 1 taken
94: branch 2 taken
1057 189: if (SLoc->isFile()) {
1058 95: const SrcMgr::FileInfo &File = SLoc->getFile();
1059 95: Record.push_back(File.getIncludeLoc().getRawEncoding());
1060 95: Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
1061 95: Record.push_back(File.hasLineDirectives());
1062 :
1063 95: const SrcMgr::ContentCache *Content = File.getContentCache();
48: branch 0 taken
47: branch 1 taken
1064 95: if (Content->Entry) {
1065 : // The source location entry is a file. The blob associated
1066 : // with this entry is the file name.
1067 :
1068 : // Turn the file name into an absolute path, if it isn't already.
1069 48: const char *Filename = Content->Entry->getName();
1070 48: llvm::sys::Path FilePath(Filename, strlen(Filename));
1071 48: std::string FilenameStr;
0: branch 1 not taken
48: branch 2 taken
1072 48: if (!FilePath.isAbsolute()) {
1073 0: llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
1074 0: P.appendComponent(FilePath.str());
1075 0: FilenameStr = P.str();
1076 0: Filename = FilenameStr.c_str();
1077 : }
1078 :
1079 48: Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
1080 48: Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename);
1081 :
1082 : // FIXME: For now, preload all file source locations, so that
1083 : // we get the appropriate File entries in the reader. This is
1084 : // a temporary measure.
1085 48: PreloadSLocs.push_back(SLocEntryOffsets.size());
1086 : } else {
1087 : // The source location entry is a buffer. The blob associated
1088 : // with this entry contains the contents of the buffer.
1089 :
1090 : // We add one to the size so that we capture the trailing NULL
1091 : // that is required by llvm::MemoryBuffer::getMemBuffer (on
1092 : // the reader side).
1093 47: const llvm::MemoryBuffer *Buffer = Content->getBuffer();
1094 47: const char *Name = Buffer->getBufferIdentifier();
1095 : Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
1096 47: llvm::StringRef(Name, strlen(Name) + 1));
1097 47: Record.clear();
1098 47: Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
1099 : Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
1100 : llvm::StringRef(Buffer->getBufferStart(),
1101 47: Buffer->getBufferSize() + 1));
1102 :
45: branch 1 taken
2: branch 2 taken
1103 47: if (strcmp(Name, "<built-in>") == 0)
1104 45: PreloadSLocs.push_back(SLocEntryOffsets.size());
1105 : }
1106 : } else {
1107 : // The source location entry is an instantiation.
1108 94: const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
1109 94: Record.push_back(Inst.getSpellingLoc().getRawEncoding());
1110 94: Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
1111 94: Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
1112 :
1113 : // Compute the token length for this macro expansion.
1114 94: unsigned NextOffset = SourceMgr.getNextOffset();
90: branch 0 taken
4: branch 1 taken
1115 94: if (I + 1 != N)
1116 90: NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset();
1117 94: Record.push_back(NextOffset - SLoc->getOffset() - 1);
1118 94: Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
1119 : }
1120 : }
1121 :
1122 44: Stream.ExitBlock();
1123 :
0: branch 1 not taken
44: branch 2 taken
1124 44: if (SLocEntryOffsets.empty())
1125 0: return;
1126 :
1127 : // Write the source-location offsets table into the PCH block. This
1128 : // table is used for lazily loading source-location information.
1129 : using namespace llvm;
1130 44: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
1131 44: Abbrev->Add(BitCodeAbbrevOp(pch::SOURCE_LOCATION_OFFSETS));
1132 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
1133 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset
1134 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets
1135 44: unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev);
1136 :
1137 44: Record.clear();
1138 44: Record.push_back(pch::SOURCE_LOCATION_OFFSETS);
1139 44: Record.push_back(SLocEntryOffsets.size());
1140 44: Record.push_back(SourceMgr.getNextOffset());
1141 : Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,
1142 : (const char *)&SLocEntryOffsets.front(),
1143 44: SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0]));
1144 :
1145 : // Write the source location entry preloads array, telling the PCH
1146 : // reader which source locations entries it should load eagerly.
44: branch 2 taken
0: branch 3 not taken
44: branch 5 taken
0: branch 6 not taken
44: branch 8 taken
0: branch 9 not taken
1147 44: Stream.EmitRecord(pch::SOURCE_LOCATION_PRELOADS, PreloadSLocs);
1148 : }
1149 :
1150 : //===----------------------------------------------------------------------===//
1151 : // Preprocessor Serialization
1152 : //===----------------------------------------------------------------------===//
1153 :
1154 : /// \brief Writes the block containing the serialized form of the
1155 : /// preprocessor.
1156 : ///
1157 44: void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
1158 44: RecordData Record;
1159 :
1160 : // If the preprocessor __COUNTER__ value has been bumped, remember it.
2: branch 1 taken
42: branch 2 taken
1161 44: if (PP.getCounterValue() != 0) {
1162 2: Record.push_back(PP.getCounterValue());
1163 2: Stream.EmitRecord(pch::PP_COUNTER_VALUE, Record);
1164 2: Record.clear();
1165 : }
1166 :
1167 : // Enter the preprocessor block.
1168 44: Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2);
1169 :
1170 : // If the PCH file contains __DATE__ or __TIME__ emit a warning about this.
1171 : // FIXME: use diagnostics subsystem for localization etc.
0: branch 1 not taken
44: branch 2 taken
1172 44: if (PP.SawDateOrTime())
1173 0: fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
1174 :
1175 : // Loop over all the macro definitions that are live at the end of the file,
1176 : // emitting each to the PP section.
5221: branch 4 taken
44: branch 5 taken
1177 5265: for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
1178 : I != E; ++I) {
1179 : // FIXME: This emits macros in hash table order, we should do it in a stable
1180 : // order so that output is reproducible.
1181 5221: MacroInfo *MI = I->second;
1182 :
1183 : // Don't emit builtin macros like __LINE__ to the PCH file unless they have
1184 : // been redefined by the header (in which case they are not isBuiltinMacro).
572: branch 1 taken
4649: branch 2 taken
1185 5221: if (MI->isBuiltinMacro())
1186 572: continue;
1187 :
1188 4649: AddIdentifierRef(I->first, Record);
1189 4649: MacroOffsets[I->first] = Stream.GetCurrentBitNo();
1190 4649: Record.push_back(MI->getDefinitionLoc().getRawEncoding());
1191 4649: Record.push_back(MI->isUsed());
1192 :
1193 : unsigned Code;
4634: branch 1 taken
15: branch 2 taken
1194 4649: if (MI->isObjectLike()) {
1195 4634: Code = pch::PP_MACRO_OBJECT_LIKE;
1196 : } else {
1197 15: Code = pch::PP_MACRO_FUNCTION_LIKE;
1198 :
1199 15: Record.push_back(MI->isC99Varargs());
1200 15: Record.push_back(MI->isGNUVarargs());
1201 15: Record.push_back(MI->getNumArgs());
24: branch 2 taken
15: branch 3 taken
1202 39: for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
1203 : I != E; ++I)
1204 24: AddIdentifierRef(*I, Record);
1205 : }
1206 4649: Stream.EmitRecord(Code, Record);
1207 4649: Record.clear();
1208 :
1209 : // Emit the tokens array.
5879: branch 1 taken
4649: branch 2 taken
1210 10528: for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
1211 : // Note that we know that the preprocessor does not have any annotation
1212 : // tokens in it because they are created by the parser, and thus can't be
1213 : // in a macro definition.
1214 5879: const Token &Tok = MI->getReplacementToken(TokNo);
1215 :
1216 5879: Record.push_back(Tok.getLocation().getRawEncoding());
1217 5879: Record.push_back(Tok.getLength());
1218 :
1219 : // FIXME: When reading literal tokens, reconstruct the literal pointer if
1220 : // it is needed.
1221 5879: AddIdentifierRef(Tok.getIdentifierInfo(), Record);
1222 :
1223 : // FIXME: Should translate token kind to a stable encoding.
1224 5879: Record.push_back(Tok.getKind());
1225 : // FIXME: Should translate token flags to a stable encoding.
1226 5879: Record.push_back(Tok.getFlags());
1227 :
1228 5879: Stream.EmitRecord(pch::PP_TOKEN, Record);
1229 5879: Record.clear();
1230 : }
1231 4649: ++NumMacros;
1232 : }
1233 44: Stream.ExitBlock();
1234 44: }
1235 :
1236 44: void PCHWriter::WriteComments(ASTContext &Context) {
1237 : using namespace llvm;
1238 :
7: branch 1 taken
37: branch 2 taken
1239 44: if (Context.Comments.empty())
1240 7: return;
1241 :
1242 37: BitCodeAbbrev *CommentAbbrev = new BitCodeAbbrev();
1243 37: CommentAbbrev->Add(BitCodeAbbrevOp(pch::COMMENT_RANGES));
1244 37: CommentAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
1245 37: unsigned CommentCode = Stream.EmitAbbrev(CommentAbbrev);
1246 :
1247 37: RecordData Record;
1248 37: Record.push_back(pch::COMMENT_RANGES);
1249 : Stream.EmitRecordWithBlob(CommentCode, Record,
1250 : (const char*)&Context.Comments[0],
1251 37: Context.Comments.size() * sizeof(SourceRange));
1252 : }
1253 :
1254 : //===----------------------------------------------------------------------===//
1255 : // Type Serialization
1256 : //===----------------------------------------------------------------------===//
1257 :
1258 : /// \brief Write the representation of a type to the PCH stream.
1259 373: void PCHWriter::WriteType(QualType T) {
1260 373: pch::TypeID &ID = TypeIDs[T];
0: branch 0 not taken
373: branch 1 taken
1261 373: if (ID == 0) // we haven't seen this type before.
1262 0: ID = NextTypeID++;
1263 :
1264 : // Record the offset for this type.
373: branch 1 taken
0: branch 2 not taken
1265 373: if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS)
1266 373: TypeOffsets.push_back(Stream.GetCurrentBitNo());
0: branch 1 not taken
0: branch 2 not taken
1267 0: else if (TypeOffsets.size() < ID - pch::NUM_PREDEF_TYPE_IDS) {
1268 0: TypeOffsets.resize(ID + 1 - pch::NUM_PREDEF_TYPE_IDS);
1269 0: TypeOffsets[ID - pch::NUM_PREDEF_TYPE_IDS] = Stream.GetCurrentBitNo();
1270 : }
1271 :
1272 373: RecordData Record;
1273 :
1274 : // Emit the type's representation.
1275 373: PCHTypeWriter W(*this, Record);
1276 :
1: branch 1 taken
372: branch 2 taken
1277 373: if (T.hasLocalNonFastQualifiers()) {
1278 1: Qualifiers Qs = T.getLocalQualifiers();
1279 1: AddTypeRef(T.getLocalUnqualifiedType(), Record);
1280 1: Record.push_back(Qs.getAsOpaqueValue());
1281 1: W.Code = pch::TYPE_EXT_QUAL;
1282 : } else {
0: branch 2 not taken
2: branch 3 taken
100: branch 4 taken
2: branch 5 taken
8: branch 6 taken
0: branch 7 not taken
0: branch 8 not taken
24: branch 9 taken
6: branch 10 taken
1: branch 11 taken
1: branch 12 taken
4: branch 13 taken
47: branch 14 taken
6: branch 15 taken
42: branch 16 taken
39: branch 17 taken
4: branch 18 taken
0: branch 19 not taken
25: branch 20 taken
5: branch 21 taken
0: branch 22 not taken
0: branch 23 not taken
0: branch 24 not taken
0: branch 25 not taken
20: branch 26 taken
36: branch 27 taken
0: branch 28 not taken
0: branch 29 not taken
1283 372: switch (T->getTypeClass()) {
1284 : // For all of the concrete, non-dependent types, call the
1285 : // appropriate visitor function.
1286 : #define TYPE(Class, Base) \
1287 : case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
1288 : #define ABSTRACT_TYPE(Class, Base)
1289 : #define DEPENDENT_TYPE(Class, Base)
1290 : #include "clang/AST/TypeNodes.def"
1291 :
1292 : // For all of the dependent type nodes (which only occur in C++
1293 : // templates), produce an error.
1294 : #define TYPE(Class, Base)
1295 : #define DEPENDENT_TYPE(Class, Base) case Type::Class:
1296 : #include "clang/AST/TypeNodes.def"
1297 0: assert(false && "Cannot serialize dependent type nodes");
1298 : break;
1299 : }
1300 : }
1301 :
1302 : // Emit the serialized record.
1303 373: Stream.EmitRecord(W.Code, Record);
1304 :
1305 : // Flush any expressions that were written as part of this type.
1306 373: FlushStmts();
1307 373: }
1308 :
1309 : //===----------------------------------------------------------------------===//
1310 : // Declaration Serialization
1311 : //===----------------------------------------------------------------------===//
1312 :
1313 : /// \brief Write the block containing all of the declaration IDs
1314 : /// lexically declared within the given DeclContext.
1315 : ///
1316 : /// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
1317 : /// bistream, or 0 if no block was written.
1318 : uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
1319 208: DeclContext *DC) {
93: branch 1 taken
115: branch 2 taken
1320 208: if (DC->decls_empty())
1321 93: return 0;
1322 :
1323 115: uint64_t Offset = Stream.GetCurrentBitNo();
1324 115: RecordData Record;
496: branch 4 taken
115: branch 5 taken
1325 611: for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
1326 : D != DEnd; ++D)
1327 496: AddDeclRef(*D, Record);
1328 :
1329 115: ++NumLexicalDeclContexts;
1330 115: Stream.EmitRecord(pch::DECL_CONTEXT_LEXICAL, Record);
1331 115: return Offset;
1332 : }
1333 :
1334 : /// \brief Write the block containing all of the declaration IDs
1335 : /// visible from the given DeclContext.
1336 : ///
1337 : /// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
1338 : /// bistream, or 0 if no block was written.
1339 : uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
1340 208: DeclContext *DC) {
5: branch 1 taken
203: branch 2 taken
1341 208: if (DC->getPrimaryContext() != DC)
1342 5: return 0;
1343 :
1344 : // Since there is no name lookup into functions or methods, and we
1345 : // perform name lookup for the translation unit via the
1346 : // IdentifierInfo chains, don't bother to build a
1347 : // visible-declarations table for these entities.
108: branch 1 taken
95: branch 2 taken
44: branch 4 taken
64: branch 5 taken
139: branch 6 taken
64: branch 7 taken
1348 203: if (DC->isFunctionOrMethod() || DC->isTranslationUnit())
1349 139: return 0;
1350 :
1351 : // Force the DeclContext to build a its name-lookup table.
1352 64: DC->lookup(DeclarationName());
1353 :
1354 : // Serialize the contents of the mapping used for lookup. Note that,
1355 : // although we have two very different code paths, the serialized
1356 : // representation is the same for both cases: a declaration name,
1357 : // followed by a size, followed by references to the visible
1358 : // declarations that have that name.
1359 64: uint64_t Offset = Stream.GetCurrentBitNo();
1360 64: RecordData Record;
1361 64: StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
20: branch 0 taken
44: branch 1 taken
1362 64: if (!Map)
1363 20: return 0;
1364 :
110: branch 5 taken
44: branch 6 taken
1365 154: for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
1366 : D != DEnd; ++D) {
1367 110: AddDeclarationName(D->first, Record);
1368 110: DeclContext::lookup_result Result = D->second.getLookupResult(Context);
1369 110: Record.push_back(Result.second - Result.first);
116: branch 0 taken
110: branch 1 taken
1370 226: for (; Result.first != Result.second; ++Result.first)
1371 116: AddDeclRef(*Result.first, Record);
1372 : }
1373 :
0: branch 1 not taken
44: branch 2 taken
1374 44: if (Record.size() == 0)
1375 0: return 0;
1376 :
1377 44: Stream.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record);
1378 44: ++NumVisibleDeclContexts;
1379 44: return Offset;
1380 : }
1381 :
1382 : //===----------------------------------------------------------------------===//
1383 : // Global Method Pool and Selector Serialization
1384 : //===----------------------------------------------------------------------===//
1385 :
1386 : namespace {
1387 : // Trait used for the on-disk hash table used in the method pool.
1388 : class PCHMethodPoolTrait {
1389 : PCHWriter &Writer;
1390 :
1391 : public:
1392 : typedef Selector key_type;
1393 : typedef key_type key_type_ref;
1394 :
1395 : typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
1396 : typedef const data_type& data_type_ref;
1397 :
1398 6: explicit PCHMethodPoolTrait(PCHWriter &Writer) : Writer(Writer) { }
1399 :
1400 25: static unsigned ComputeHash(Selector Sel) {
1401 25: unsigned N = Sel.getNumArgs();
20: branch 0 taken
5: branch 1 taken
1402 25: if (N == 0)
1403 20: ++N;
1404 25: unsigned R = 5381;
25: branch 0 taken
25: branch 1 taken
1405 50: for (unsigned I = 0; I != N; ++I)
25: branch 1 taken
0: branch 2 not taken
1406 25: if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
1407 25: R = llvm::HashString(II->getName(), R);
1408 25: return R;
1409 : }
1410 :
1411 : std::pair<unsigned,unsigned>
1412 : EmitKeyDataLength(llvm::raw_ostream& Out, Selector Sel,
1413 25: data_type_ref Methods) {
5: branch 1 taken
20: branch 2 taken
1414 25: unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
1415 25: clang::io::Emit16(Out, KeyLen);
1416 25: unsigned DataLen = 2 + 2; // 2 bytes for each of the method counts
26: branch 0 taken
25: branch 1 taken
1417 51: for (const ObjCMethodList *Method = &Methods.first; Method;
1418 : Method = Method->Next)
20: branch 0 taken
6: branch 1 taken
1419 26: if (Method->Method)
1420 20: DataLen += 4;
25: branch 0 taken
25: branch 1 taken
1421 50: for (const ObjCMethodList *Method = &Methods.second; Method;
1422 : Method = Method->Next)
6: branch 0 taken
19: branch 1 taken
1423 25: if (Method->Method)
1424 6: DataLen += 4;
1425 25: clang::io::Emit16(Out, DataLen);
1426 25: return std::make_pair(KeyLen, DataLen);
1427 : }
1428 :
1429 25: void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) {
1430 25: uint64_t Start = Out.tell();
0: branch 0 not taken
25: branch 1 taken
1431 25: assert((Start >> 32) == 0 && "Selector key offset too large");
1432 25: Writer.SetSelectorOffset(Sel, Start);
1433 25: unsigned N = Sel.getNumArgs();
1434 25: clang::io::Emit16(Out, N);
20: branch 0 taken
5: branch 1 taken
1435 25: if (N == 0)
1436 20: N = 1;
25: branch 0 taken
25: branch 1 taken
1437 50: for (unsigned I = 0; I != N; ++I)
1438 : clang::io::Emit32(Out,
1439 25: Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
1440 25: }
1441 :
1442 : void EmitData(llvm::raw_ostream& Out, key_type_ref,
1443 25: data_type_ref Methods, unsigned DataLen) {
1444 25: uint64_t Start = Out.tell(); (void)Start;
1445 25: unsigned NumInstanceMethods = 0;
26: branch 0 taken
25: branch 1 taken
1446 51: for (const ObjCMethodList *Method = &Methods.first; Method;
1447 : Method = Method->Next)
20: branch 0 taken
6: branch 1 taken
1448 26: if (Method->Method)
1449 20: ++NumInstanceMethods;
1450 :
1451 25: unsigned NumFactoryMethods = 0;
25: branch 0 taken
25: branch 1 taken
1452 50: for (const ObjCMethodList *Method = &Methods.second; Method;
1453 : Method = Method->Next)
6: branch 0 taken
19: branch 1 taken
1454 25: if (Method->Method)
1455 6: ++NumFactoryMethods;
1456 :
1457 25: clang::io::Emit16(Out, NumInstanceMethods);
1458 25: clang::io::Emit16(Out, NumFactoryMethods);
26: branch 0 taken
25: branch 1 taken
1459 51: for (const ObjCMethodList *Method = &Methods.first; Method;
1460 : Method = Method->Next)
20: branch 0 taken
6: branch 1 taken
1461 26: if (Method->Method)
1462 20: clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
25: branch 0 taken
25: branch 1 taken
1463 50: for (const ObjCMethodList *Method = &Methods.second; Method;
1464 : Method = Method->Next)
6: branch 0 taken
19: branch 1 taken
1465 25: if (Method->Method)
1466 6: clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
1467 :
25: branch 1 taken
0: branch 2 not taken
1468 25: assert(Out.tell() - Start == DataLen && "Data length is wrong");
1469 25: }
1470 : };
1471 : } // end anonymous namespace
1472 :
1473 : /// \brief Write the method pool into the PCH file.
1474 : ///
1475 : /// The method pool contains both instance and factory methods, stored
1476 : /// in an on-disk hash table indexed by the selector.
1477 44: void PCHWriter::WriteMethodPool(Sema &SemaRef) {
1478 : using namespace llvm;
1479 :
1480 : // Create and write out the blob that contains the instance and
1481 : // factor method pools.
1482 44: bool Empty = true;
1483 : {
1484 44: OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator;
1485 :
1486 : // Create the on-disk hash table representation. Start by
1487 : // iterating through the instance method pool.
1488 44: PCHMethodPoolTrait::key_type Key;
1489 44: unsigned NumSelectorsInMethodPool = 0;
19: branch 3 taken
44: branch 4 taken
1490 63: for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
1491 44: Instance = SemaRef.InstanceMethodPool.begin(),
1492 44: InstanceEnd = SemaRef.InstanceMethodPool.end();
1493 : Instance != InstanceEnd; ++Instance) {
1494 : // Check whether there is a factory method with the same
1495 : // selector.
1496 : llvm::DenseMap<Selector, ObjCMethodList>::iterator Factory
1497 19: = SemaRef.FactoryMethodPool.find(Instance->first);
1498 :
19: branch 3 taken
0: branch 4 not taken
1499 19: if (Factory == SemaRef.FactoryMethodPool.end())
1500 : Generator.insert(Instance->first,
1501 : std::make_pair(Instance->second,
1502 19: ObjCMethodList()));
1503 : else
1504 : Generator.insert(Instance->first,
1505 0: std::make_pair(Instance->second, Factory->second));
1506 :
1507 19: ++NumSelectorsInMethodPool;
1508 19: Empty = false;
1509 : }
1510 :
1511 : // Now iterate through the factory method pool, to pick up any
1512 : // selectors that weren't already in the instance method pool.
6: branch 3 taken
44: branch 4 taken
1513 50: for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
1514 44: Factory = SemaRef.FactoryMethodPool.begin(),
1515 44: FactoryEnd = SemaRef.FactoryMethodPool.end();
1516 : Factory != FactoryEnd; ++Factory) {
1517 : // Check whether there is an instance method with the same
1518 : // selector. If so, there is no work to do here.
1519 : llvm::DenseMap<Selector, ObjCMethodList>::iterator Instance
1520 6: = SemaRef.InstanceMethodPool.find(Factory->first);
1521 :
6: branch 3 taken
0: branch 4 not taken
1522 6: if (Instance == SemaRef.InstanceMethodPool.end()) {
1523 : Generator.insert(Factory->first,
1524 6: std::make_pair(ObjCMethodList(), Factory->second));
1525 6: ++NumSelectorsInMethodPool;
1526 : }
1527 :
1528 6: Empty = false;
1529 : }
1530 :
38: branch 0 taken
6: branch 1 taken
38: branch 3 taken
0: branch 4 not taken
38: branch 5 taken
6: branch 6 taken
1531 44: if (Empty && SelectorOffsets.empty())
1532 38: return;
1533 :
1534 : // Create the on-disk hash table in a buffer.
1535 6: llvm::SmallString<4096> MethodPool;
1536 : uint32_t BucketOffset;
1537 6: SelectorOffsets.resize(SelVector.size());
1538 : {
1539 6: PCHMethodPoolTrait Trait(*this);
1540 6: llvm::raw_svector_ostream Out(MethodPool);
1541 : // Make sure that no bucket is at offset 0
1542 6: clang::io::Emit32(Out, 0);
1543 6: BucketOffset = Generator.Emit(Out, Trait);
1544 :
1545 : // For every selector that we have seen but which was not
1546 : // written into the hash table, write the selector itself and
1547 : // record it's offset.
25: branch 1 taken
6: branch 2 taken
1548 31: for (unsigned I = 0, N = SelVector.size(); I != N; ++I)
0: branch 1 not taken
25: branch 2 taken
1549 25: if (SelectorOffsets[I] == 0)
1550 6: Trait.EmitKey(Out, SelVector[I], 0);
1551 : }
1552 :
1553 : // Create a blob abbreviation
1554 6: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
1555 6: Abbrev->Add(BitCodeAbbrevOp(pch::METHOD_POOL));
1556 6: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
1557 6: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
1558 6: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
1559 6: unsigned MethodPoolAbbrev = Stream.EmitAbbrev(Abbrev);
1560 :
1561 : // Write the method pool
1562 6: RecordData Record;
1563 6: Record.push_back(pch::METHOD_POOL);
1564 6: Record.push_back(BucketOffset);
1565 6: Record.push_back(NumSelectorsInMethodPool);
1566 6: Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str());
1567 :
1568 : // Create a blob abbreviation for the selector table offsets.
1569 6: Abbrev = new BitCodeAbbrev();
1570 6: Abbrev->Add(BitCodeAbbrevOp(pch::SELECTOR_OFFSETS));
1571 6: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index
1572 6: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
1573 6: unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
1574 :
1575 : // Write the selector offsets table.
1576 6: Record.clear();
1577 6: Record.push_back(pch::SELECTOR_OFFSETS);
1578 6: Record.push_back(SelectorOffsets.size());
1579 : Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
1580 : (const char *)&SelectorOffsets.front(),
6: branch 6 taken
38: branch 7 taken
1581 6: SelectorOffsets.size() * 4);
1582 : }
1583 : }
1584 :
1585 : //===----------------------------------------------------------------------===//
1586 : // Identifier Table Serialization
1587 : //===----------------------------------------------------------------------===//
1588 :
1589 : namespace {
1590 : class PCHIdentifierTableTrait {
1591 : PCHWriter &Writer;
1592 : Preprocessor &PP;
1593 :
1594 : /// \brief Determines whether this is an "interesting" identifier
1595 : /// that needs a full IdentifierInfo structure written into the hash
1596 : /// table.
1597 79372: static bool isInterestingIdentifier(const IdentifierInfo *II) {
1598 : return II->isPoisoned() ||
1599 : II->isExtensionToken() ||
1600 : II->hasMacroDefinition() ||
1601 : II->getObjCOrBuiltinID() ||
79284: branch 1 taken
88: branch 2 taken
79116: branch 4 taken
168: branch 5 taken
68674: branch 7 taken
10442: branch 8 taken
10310: branch 10 taken
58364: branch 11 taken
608: branch 13 taken
9702: branch 14 taken
1602 79372: II->getFETokenInfo<void>();
1603 : }
1604 :
1605 : public:
1606 : typedef const IdentifierInfo* key_type;
1607 : typedef key_type key_type_ref;
1608 :
1609 : typedef pch::IdentID data_type;
1610 : typedef data_type data_type_ref;
1611 :
1612 44: PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP)
1613 44: : Writer(Writer), PP(PP) { }
1614 :
1615 39686: static unsigned ComputeHash(const IdentifierInfo* II) {
1616 39686: return llvm::HashString(II->getName());
1617 : }
1618 :
1619 : std::pair<unsigned,unsigned>
1620 : EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II,
1621 39686: pch::IdentID ID) {
1622 39686: unsigned KeyLen = II->getLength() + 1;
1623 39686: unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
34835: branch 1 taken
4851: branch 2 taken
1624 39686: if (isInterestingIdentifier(II)) {
1625 34835: DataLen += 2; // 2 bytes for builtin ID, flags
5221: branch 1 taken
29614: branch 2 taken
4649: branch 5 taken
572: branch 6 taken
4649: branch 7 taken
30186: branch 8 taken
1626 34835: if (II->hasMacroDefinition() &&
1627 : !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro())
1628 4649: DataLen += 4;
319: branch 4 taken
34835: branch 5 taken
1629 69989: for (IdentifierResolver::iterator D = IdentifierResolver::begin(II),
1630 34835: DEnd = IdentifierResolver::end();
1631 : D != DEnd; ++D)
1632 319: DataLen += sizeof(pch::DeclID);
1633 : }
1634 39686: clang::io::Emit16(Out, DataLen);
1635 : // We emit the key length after the data length so that every
1636 : // string is preceded by a 16-bit length. This matches the PTH
1637 : // format for storing identifiers.
1638 39686: clang::io::Emit16(Out, KeyLen);
1639 39686: return std::make_pair(KeyLen, DataLen);
1640 : }
1641 :
1642 : void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II,
1643 39686: unsigned KeyLen) {
1644 : // Record the location of the key data. This is used when generating
1645 : // the mapping from persistent IDs to strings.
1646 39686: Writer.SetIdentifierOffset(II, Out.tell());
1647 39686: Out.write(II->getNameStart(), KeyLen);
1648 39686: }
1649 :
1650 : void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II,
1651 39686: pch::IdentID ID, unsigned) {
4851: branch 1 taken
34835: branch 2 taken
1652 39686: if (!isInterestingIdentifier(II)) {
1653 4851: clang::io::Emit32(Out, ID << 1);
1654 4851: return;
1655 : }
1656 :
1657 34835: clang::io::Emit32(Out, (ID << 1) | 0x01);
1658 34835: uint32_t Bits = 0;
1659 : bool hasMacroDefinition =
1660 : II->hasMacroDefinition() &&
5221: branch 1 taken
29614: branch 2 taken
4649: branch 5 taken
572: branch 6 taken
1661 34835: !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro();
1662 34835: Bits = (uint32_t)II->getObjCOrBuiltinID();
1663 34835: Bits = (Bits << 1) | unsigned(hasMacroDefinition);
1664 34835: Bits = (Bits << 1) | unsigned(II->isExtensionToken());
1665 34835: Bits = (Bits << 1) | unsigned(II->isPoisoned());
1666 34835: Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
1667 34835: clang::io::Emit16(Out, Bits);
1668 :
4649: branch 0 taken
30186: branch 1 taken
1669 34835: if (hasMacroDefinition)
1670 4649: clang::io::Emit32(Out, Writer.getMacroOffset(II));
1671 :
1672 : // Emit the declaration IDs in reverse order, because the
1673 : // IdentifierResolver provides the declarations as they would be
1674 : // visible (e.g., the function "stat" would come before the struct
1675 : // "stat"), but IdentifierResolver::AddDeclToIdentifierChain()
1676 : // adds declarations to the end of the list (so we need to see the
1677 : // struct "status" before the function "status").
1678 : llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II),
1679 34835: IdentifierResolver::end());
319: branch 3 taken
34835: branch 4 taken
1680 69989: for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(),
1681 34835: DEnd = Decls.rend();
1682 : D != DEnd; ++D)
1683 35154: clang::io::Emit32(Out, Writer.getDeclID(*D));
1684 : }
1685 : };
1686 : } // end anonymous namespace
1687 :
1688 : /// \brief Write the identifier table into the PCH file.
1689 : ///
1690 : /// The identifier table consists of a blob containing string data
1691 : /// (the actual identifiers themselves) and a separate "offsets" index
1692 : /// that maps identifier IDs to locations within the blob.
1693 44: void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
1694 : using namespace llvm;
1695 :
1696 : // Create and write out the blob that contains the identifier
1697 : // strings.
1698 : {
1699 44: OnDiskChainedHashTableGenerator<PCHIdentifierTableTrait> Generator;
1700 :
1701 : // Look for any identifiers that were named while processing the
1702 : // headers, but are otherwise not needed. We add these to the hash
1703 : // table to enable checking of the predefines buffer in the case
1704 : // where the user adds new macro definitions when building the PCH
1705 : // file.
39686: branch 4 taken
44: branch 5 taken
1706 39774: for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
1707 44: IDEnd = PP.getIdentifierTable().end();
1708 : ID != IDEnd; ++ID)
1709 39686: getIdentifierRef(ID->second);
1710 :
1711 : // Create the on-disk hash table representation.
1712 44: IdentifierOffsets.resize(IdentifierIDs.size());
39686: branch 3 taken
44: branch 4 taken
1713 39730: for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator
1714 44: ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
1715 : ID != IDEnd; ++ID) {
39686: branch 1 taken
0: branch 2 not taken
1716 39686: assert(ID->first && "NULL identifier in identifier table");
1717 39686: Generator.insert(ID->first, ID->second);
1718 : }
1719 :
1720 : // Create the on-disk hash table in a buffer.
1721 44: llvm::SmallString<4096> IdentifierTable;
1722 : uint32_t BucketOffset;
1723 : {
1724 44: PCHIdentifierTableTrait Trait(*this, PP);
1725 44: llvm::raw_svector_ostream Out(IdentifierTable);
1726 : // Make sure that no bucket is at offset 0
1727 44: clang::io::Emit32(Out, 0);
1728 44: BucketOffset = Generator.Emit(Out, Trait);
1729 : }
1730 :
1731 : // Create a blob abbreviation
1732 44: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
1733 44: Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE));
1734 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
1735 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
1736 44: unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);
1737 :
1738 : // Write the identifier table
1739 44: RecordData Record;
1740 44: Record.push_back(pch::IDENTIFIER_TABLE);
1741 44: Record.push_back(BucketOffset);
1742 44: Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str());
1743 : }
1744 :
1745 : // Write the offsets table for identifier IDs.
1746 44: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
1747 44: Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_OFFSET));
1748 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers
1749 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
1750 44: unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
1751 :
1752 44: RecordData Record;
1753 44: Record.push_back(pch::IDENTIFIER_OFFSET);
1754 44: Record.push_back(IdentifierOffsets.size());
1755 : Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
1756 : (const char *)&IdentifierOffsets.front(),
1757 44: IdentifierOffsets.size() * sizeof(uint32_t));
1758 44: }
1759 :
1760 : //===----------------------------------------------------------------------===//
1761 : // General Serialization Routines
1762 : //===----------------------------------------------------------------------===//
1763 :
1764 : /// \brief Write a record containing the given attributes.
1765 7: void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
1766 7: RecordData Record;
8: branch 1 taken
7: branch 2 taken
1767 15: for (; Attr; Attr = Attr->getNext()) {
1768 8: Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs
1769 8: Record.push_back(Attr->isInherited());
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
1: branch 9 taken
0: branch 10 not taken
0: branch 11 not taken
1: branch 12 taken
0: branch 13 not taken
0: branch 14 not taken
0: branch 15 not taken
0: branch 16 not taken
4: branch 17 taken
0: branch 18 not taken
0: branch 19 not taken
1: branch 20 taken
0: branch 21 not taken
1: branch 22 taken
0: branch 23 not taken
0: branch 24 not taken
0: branch 25 not taken
0: branch 26 not taken
0: branch 27 not taken
0: branch 28 not taken
0: branch 29 not taken
0: branch 30 not taken
0: branch 31 not taken
1770 8: switch (Attr->getKind()) {
1771 : default:
1772 0: assert(0 && "Does not support PCH writing for this attribute yet!");
1773 : break;
1774 : case Attr::Alias:
1775 0: AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
1776 0: break;
1777 :
1778 : case Attr::Aligned:
1779 0: Record.push_back(cast<AlignedAttr>(Attr)->getAlignment());
1780 0: break;
1781 :
1782 : case Attr::AlwaysInline:
1783 0: break;
1784 :
1785 : case Attr::AnalyzerNoReturn:
1786 0: break;
1787 :
1788 : case Attr::Annotate:
1789 0: AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record);
1790 0: break;
1791 :
1792 : case Attr::AsmLabel:
1793 0: AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
1794 0: break;
1795 :
1796 : case Attr::BaseCheck:
1797 0: break;
1798 :
1799 : case Attr::Blocks:
1800 1: Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
1801 1: break;
1802 :
1803 : case Attr::CDecl:
1804 0: break;
1805 :
1806 : case Attr::Cleanup:
1807 0: AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
1808 0: break;
1809 :
1810 : case Attr::Const:
1811 1: break;
1812 :
1813 : case Attr::Constructor:
1814 0: Record.push_back(cast<ConstructorAttr>(Attr)->getPriority());
1815 0: break;
1816 :
1817 : case Attr::DLLExport:
1818 : case Attr::DLLImport:
1819 : case Attr::Deprecated:
1820 0: break;
1821 :
1822 : case Attr::Destructor:
1823 0: Record.push_back(cast<DestructorAttr>(Attr)->getPriority());
1824 0: break;
1825 :
1826 : case Attr::FastCall:
1827 : case Attr::Final:
1828 0: break;
1829 :
1830 : case Attr::Format: {
1831 4: const FormatAttr *Format = cast<FormatAttr>(Attr);
1832 4: AddString(Format->getType(), Record);
1833 4: Record.push_back(Format->getFormatIdx());
1834 4: Record.push_back(Format->getFirstArg());
1835 4: break;
1836 : }
1837 :
1838 : case Attr::FormatArg: {
1839 0: const FormatArgAttr *Format = cast<FormatArgAttr>(Attr);
1840 0: Record.push_back(Format->getFormatIdx());
1841 0: break;
1842 : }
1843 :
1844 : case Attr::Sentinel : {
1845 0: const SentinelAttr *Sentinel = cast<SentinelAttr>(Attr);
1846 0: Record.push_back(Sentinel->getSentinel());
1847 0: Record.push_back(Sentinel->getNullPos());
1848 0: break;
1849 : }
1850 :
1851 : case Attr::GNUInline:
1852 : case Attr::Hiding:
1853 : case Attr::IBOutletKind:
1854 : case Attr::Malloc:
1855 : case Attr::NoDebug:
1856 : case Attr::NoReturn:
1857 : case Attr::NoThrow:
1858 : case Attr::NoInline:
1859 1: break;
1860 :
1861 : case Attr::NonNull: {
1862 0: const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
1863 0: Record.push_back(NonNull->size());
1864 0: Record.insert(Record.end(), NonNull->begin(), NonNull->end());
1865 0: break;
1866 : }
1867 :
1868 : case Attr::ObjCException:
1869 : case Attr::ObjCNSObject:
1870 : case Attr::CFReturnsRetained:
1871 : case Attr::NSReturnsRetained:
1872 : case Attr::Overloadable:
1873 : case Attr::Override:
1874 1: break;
1875 :
1876 : case Attr::PragmaPack:
1877 0: Record.push_back(cast<PragmaPackAttr>(Attr)->getAlignment());
1878 0: break;
1879 :
1880 : case Attr::Packed:
1881 0: break;
1882 :
1883 : case Attr::Pure:
1884 0: break;
1885 :
1886 : case Attr::Regparm:
1887 0: Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
1888 0: break;
1889 :
1890 : case Attr::ReqdWorkGroupSize:
1891 0: Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim());
1892 0: Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim());
1893 0: Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim());
1894 0: break;
1895 :
1896 : case Attr::Section:
1897 0: AddString(cast<SectionAttr>(Attr)->getName(), Record);
1898 0: break;
1899 :
1900 : case Attr::StdCall:
1901 : case Attr::TransparentUnion:
1902 : case Attr::Unavailable:
1903 : case Attr::Unused:
1904 : case Attr::Used:
1905 0: break;
1906 :
1907 : case Attr::Visibility:
1908 : // FIXME: stable encoding
1909 0: Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility());
1910 : break;
1911 :
1912 : case Attr::WarnUnusedResult:
1913 : case Attr::Weak:
1914 : case Attr::WeakImport:
1915 : break;
1916 : }
1917 : }
1918 :
1919 7: Stream.EmitRecord(pch::DECL_ATTR, Record);
1920 7: }
1921 :
1922 4: void PCHWriter::AddString(const std::string &Str, RecordData &Record) {
1923 4: Record.push_back(Str.size());
1924 4: Record.insert(Record.end(), Str.begin(), Str.end());
1925 4: }
1926 :
1927 : /// \brief Note that the identifier II occurs at the given offset
1928 : /// within the identifier table.
1929 39686: void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
1930 39686: IdentifierOffsets[IdentifierIDs[II] - 1] = Offset;
1931 39686: }
1932 :
1933 : /// \brief Note that the selector Sel occurs at the given offset
1934 : /// within the method pool/selector table.
1935 25: void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
1936 25: unsigned ID = SelectorIDs[Sel];
0: branch 0 not taken
25: branch 1 taken
1937 25: assert(ID && "Unknown selector");
1938 25: SelectorOffsets[ID - 1] = Offset;
1939 25: }
1940 :
1941 44: PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
1942 : : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS),
1943 : NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
1944 44: NumVisibleDeclContexts(0) { }
1945 :
1946 : void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
1947 44: const char *isysroot) {
1948 : using namespace llvm;
1949 :
1950 44: ASTContext &Context = SemaRef.Context;
1951 44: Preprocessor &PP = SemaRef.PP;
1952 :
1953 : // Emit the file header.
1954 44: Stream.Emit((unsigned)'C', 8);
1955 44: Stream.Emit((unsigned)'P', 8);
1956 44: Stream.Emit((unsigned)'C', 8);
1957 44: Stream.Emit((unsigned)'H', 8);
1958 :
1959 44: WriteBlockInfoBlock();
1960 :
1961 : // The translation unit is the first declaration we'll emit.
1962 44: DeclIDs[Context.getTranslationUnitDecl()] = 1;
1963 44: DeclTypesToEmit.push(Context.getTranslationUnitDecl());
1964 :
1965 : // Make sure that we emit IdentifierInfos (and any attached
1966 : // declarations) for builtins.
1967 : {
1968 44: IdentifierTable &Table = PP.getIdentifierTable();
1969 44: llvm::SmallVector<const char *, 32> BuiltinNames;
1970 : Context.BuiltinInfo.GetBuiltinNames(BuiltinNames,
1971 44: Context.getLangOptions().NoBuiltin);
28952: branch 1 taken
44: branch 2 taken
1972 28996: for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I)
1973 28996: getIdentifierRef(&Table.get(BuiltinNames[I]));
1974 : }
1975 :
1976 : // Build a record containing all of the tentative definitions in this file, in
1977 : // TentativeDefinitions order. Generally, this record will be empty for
1978 : // headers.
1979 44: RecordData TentativeDefinitions;
29: branch 1 taken
44: branch 2 taken
1980 73: for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) {
1981 29: AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
1982 : }
1983 :
1984 : // Build a record containing all of the locally-scoped external
1985 : // declarations in this header file. Generally, this record will be
1986 : // empty.
1987 44: RecordData LocallyScopedExternalDecls;
1988 : // FIXME: This is filling in the PCH file in densemap order which is
1989 : // nondeterminstic!
4: branch 3 taken
44: branch 4 taken
1990 48: for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
1991 44: TD = SemaRef.LocallyScopedExternalDecls.begin(),
1992 44: TDEnd = SemaRef.LocallyScopedExternalDecls.end();
1993 : TD != TDEnd; ++TD)
1994 4: AddDeclRef(TD->second, LocallyScopedExternalDecls);
1995 :
1996 : // Build a record containing all of the ext_vector declarations.
1997 44: RecordData ExtVectorDecls;
4: branch 1 taken
44: branch 2 taken
1998 48: for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I)
1999 4: AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls);
2000 :
2001 : // Write the remaining PCH contents.
2002 44: RecordData Record;
2003 44: Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4);
2004 44: WriteMetadata(Context, isysroot);
2005 44: WriteLanguageOptions(Context.getLangOptions());
44: branch 0 taken
0: branch 1 not taken
43: branch 2 taken
1: branch 3 taken
2006 44: if (StatCalls && !isysroot)
2007 43: WriteStatCache(*StatCalls, isysroot);
2008 44: WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
2009 44: WriteComments(Context);
2010 : // Write the record of special types.
2011 44: Record.clear();
2012 :
2013 44: AddTypeRef(Context.getBuiltinVaListType(), Record);
2014 44: AddTypeRef(Context.getObjCIdType(), Record);
2015 44: AddTypeRef(Context.getObjCSelType(), Record);
2016 44: AddTypeRef(Context.getObjCProtoType(), Record);
2017 44: AddTypeRef(Context.getObjCClassType(), Record);
2018 44: AddTypeRef(Context.getRawCFConstantStringType(), Record);
2019 44: AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record);
2020 44: AddTypeRef(Context.getFILEType(), Record);
2021 44: AddTypeRef(Context.getjmp_bufType(), Record);
2022 44: AddTypeRef(Context.getsigjmp_bufType(), Record);
2023 44: AddTypeRef(Context.ObjCIdRedefinitionType, Record);
2024 44: AddTypeRef(Context.ObjCClassRedefinitionType, Record);
2025 : #if 0
2026 : // FIXME. Accommodate for this in several PCH/Indexer tests
2027 : AddTypeRef(Context.ObjCSelRedefinitionType, Record);
2028 : #endif
2029 44: AddTypeRef(Context.getRawBlockdescriptorType(), Record);
2030 44: AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record);
2031 44: Stream.EmitRecord(pch::SPECIAL_TYPES, Record);
2032 :
2033 : // Keep writing types and declarations until all types and
2034 : // declarations have been written.
2035 44: Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
2036 44: WriteDeclsBlockAbbrevs();
975: branch 1 taken
44: branch 2 taken
2037 1063: while (!DeclTypesToEmit.empty()) {
2038 975: DeclOrType DOT = DeclTypesToEmit.front();
2039 975: DeclTypesToEmit.pop();
373: branch 1 taken
602: branch 2 taken
2040 975: if (DOT.isType())
2041 373: WriteType(DOT.getType());
2042 : else
2043 602: WriteDecl(Context, DOT.getDecl());
2044 : }
2045 44: Stream.ExitBlock();
2046 :
2047 44: WritePreprocessor(PP);
2048 44: WriteMethodPool(SemaRef);
2049 44: WriteIdentifierTable(PP);
2050 :
2051 : // Write the type offsets array
2052 44: BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
2053 44: Abbrev->Add(BitCodeAbbrevOp(pch::TYPE_OFFSET));
2054 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
2055 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
2056 44: unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
2057 44: Record.clear();
2058 44: Record.push_back(pch::TYPE_OFFSET);
2059 44: Record.push_back(TypeOffsets.size());
2060 : Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record,
2061 : (const char *)&TypeOffsets.front(),
2062 44: TypeOffsets.size() * sizeof(TypeOffsets[0]));
2063 :
2064 : // Write the declaration offsets array
2065 44: Abbrev = new BitCodeAbbrev();
2066 44: Abbrev->Add(BitCodeAbbrevOp(pch::DECL_OFFSET));
2067 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
2068 44: Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
2069 44: unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
2070 44: Record.clear();
2071 44: Record.push_back(pch::DECL_OFFSET);
2072 44: Record.push_back(DeclOffsets.size());
2073 : Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record,
2074 : (const char *)&DeclOffsets.front(),
2075 44: DeclOffsets.size() * sizeof(DeclOffsets[0]));
2076 :
2077 : // Write the record containing external, unnamed definitions.
21: branch 1 taken
23: branch 2 taken
2078 44: if (!ExternalDefinitions.empty())
2079 21: Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions);
2080 :
2081 : // Write the record containing tentative definitions.
11: branch 1 taken
33: branch 2 taken
2082 44: if (!TentativeDefinitions.empty())
2083 11: Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions);
2084 :
2085 : // Write the record containing locally-scoped external definitions.
2: branch 1 taken
42: branch 2 taken
2086 44: if (!LocallyScopedExternalDecls.empty())
2087 : Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS,
2088 2: LocallyScopedExternalDecls);
2089 :
2090 : // Write the record containing ext_vector type names.
3: branch 1 taken
41: branch 2 taken
2091 44: if (!ExtVectorDecls.empty())
2092 3: Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls);
2093 :
2094 : // Some simple statistics
2095 44: Record.clear();
2096 44: Record.push_back(NumStatements);
2097 44: Record.push_back(NumMacros);
2098 44: Record.push_back(NumLexicalDeclContexts);
2099 44: Record.push_back(NumVisibleDeclContexts);
2100 44: Stream.EmitRecord(pch::STATISTICS, Record);
2101 44: Stream.ExitBlock();
2102 44: }
2103 :
2104 2540: void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
2105 2540: Record.push_back(Loc.getRawEncoding());
2106 2540: }
2107 :
2108 124: void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
2109 124: Record.push_back(Value.getBitWidth());
2110 124: unsigned N = Value.getNumWords();
2111 124: const uint64_t* Words = Value.getRawData();
124: branch 0 taken
124: branch 1 taken
2112 248: for (unsigned I = 0; I != N; ++I)
2113 124: Record.push_back(Words[I]);
2114 124: }
2115 :
2116 10: void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) {
2117 10: Record.push_back(Value.isUnsigned());
2118 10: AddAPInt(Value, Record);
2119 10: }
2120 :
2121 12: void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) {
2122 12: AddAPInt(Value.bitcastToAPInt(), Record);
2123 12: }
2124 :
2125 11182: void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
2126 11182: Record.push_back(getIdentifierRef(II));
2127 11182: }
2128 :
2129 79845: pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) {
4984: branch 0 taken
74861: branch 1 taken
2130 79845: if (II == 0)
2131 4984: return 0;
2132 :
2133 74861: pch::IdentID &ID = IdentifierIDs[II];
39686: branch 0 taken
35175: branch 1 taken
2134 74861: if (ID == 0)
2135 39686: ID = IdentifierIDs.size();
2136 74861: return ID;
2137 : }
2138 :
2139 75: void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
0: branch 1 not taken
75: branch 2 taken
2140 75: if (SelRef.getAsOpaquePtr() == 0) {
2141 0: Record.push_back(0);
2142 0: return;
2143 : }
2144 :
2145 75: pch::SelectorID &SID = SelectorIDs[SelRef];
28: branch 0 taken
47: branch 1 taken
2146 75: if (SID == 0) {
2147 28: SID = SelectorIDs.size();
2148 28: SelVector.push_back(SelRef);
2149 : }
2150 75: Record.push_back(SID);
2151 : }
2152 :
2153 : void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
2154 0: RecordData &Record) {
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
2155 0: switch (Arg.getArgument().getKind()) {
2156 : case TemplateArgument::Expression:
2157 0: AddStmt(Arg.getLocInfo().getAsExpr());
2158 0: break;
2159 : case TemplateArgument::Type:
2160 0: AddTypeSourceInfo(Arg.getLocInfo().getAsTypeSourceInfo(), Record);
2161 0: break;
2162 : case TemplateArgument::Template:
2163 : Record.push_back(
2164 0: Arg.getTemplateQualifierRange().getBegin().getRawEncoding());
2165 0: Record.push_back(Arg.getTemplateQualifierRange().getEnd().getRawEncoding());
2166 0: Record.push_back(Arg.getTemplateNameLoc().getRawEncoding());
2167 : break;
2168 : case TemplateArgument::Null:
2169 : case TemplateArgument::Integral:
2170 : case TemplateArgument::Declaration:
2171 : case TemplateArgument::Pack:
2172 : break;
2173 : }
2174 0: }
2175 :
2176 458: void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) {
38: branch 0 taken
420: branch 1 taken
2177 458: if (TInfo == 0) {
2178 38: AddTypeRef(QualType(), Record);
2179 38: return;
2180 : }
2181 :
2182 420: AddTypeRef(TInfo->getType(), Record);
2183 420: TypeLocWriter TLW(*this, Record);
648: branch 3 taken
420: branch 4 taken
2184 1068: for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
2185 648: TLW.Visit(TL);
2186 : }
2187 :
2188 2420: void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
731: branch 1 taken
1689: branch 2 taken
2189 2420: if (T.isNull()) {
2190 731: Record.push_back(pch::PREDEF_TYPE_NULL_ID);
2191 731: return;
2192 : }
2193 :
2194 1689: unsigned FastQuals = T.getLocalFastQualifiers();
2195 1689: T.removeFastQualifiers();
2196 :
1: branch 1 taken
1688: branch 2 taken
2197 1689: if (T.hasLocalNonFastQualifiers()) {
2198 1: pch::TypeID &ID = TypeIDs[T];
1: branch 0 taken
0: branch 1 not taken
2199 1: if (ID == 0) {
2200 : // We haven't seen these qualifiers applied to this type before.
2201 : // Assign it a new ID. This is the only time we enqueue a
2202 : // qualified type, and it has no CV qualifiers.
2203 1: ID = NextTypeID++;
2204 1: DeclTypesToEmit.push(T);
2205 : }
2206 :
2207 : // Encode the type qualifiers in the type reference.
2208 1: Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
2209 1: return;
2210 : }
2211 :
0: branch 1 not taken
1688: branch 2 taken
2212 1688: assert(!T.hasLocalQualifiers());
2213 :
826: branch 2 taken
862: branch 3 taken
2214 1688: if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
2215 826: pch::TypeID ID = 0;
40: branch 1 taken
9: branch 2 taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
44: branch 6 taken
0: branch 7 not taken
0: branch 8 not taken
7: branch 9 taken
72: branch 10 taken
0: branch 11 not taken
0: branch 12 not taken
0: branch 13 not taken
472: branch 14 taken
2: branch 15 taken
0: branch 16 not taken
7: branch 17 taken
79: branch 18 taken
57: branch 19 taken
0: branch 20 not taken
2: branch 21 taken
0: branch 22 not taken
0: branch 23 not taken
0: branch 24 not taken
0: branch 25 not taken
15: branch 26 taken
10: branch 27 taken
10: branch 28 taken
0: branch 29 not taken
0: branch 30 not taken
2216 826: switch (BT->getKind()) {
2217 40: case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break;
2218 9: case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break;
2219 0: case BuiltinType::Char_U: ID = pch::PREDEF_TYPE_CHAR_U_ID; break;
2220 0: case BuiltinType::UChar: ID = pch::PREDEF_TYPE_UCHAR_ID; break;
2221 0: case BuiltinType::UShort: ID = pch::PREDEF_TYPE_USHORT_ID; break;
2222 44: case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break;
2223 0: case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break;
2224 0: case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break;
2225 7: case BuiltinType::UInt128: ID = pch::PREDEF_TYPE_UINT128_ID; break;
2226 72: case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break;
2227 0: case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break;
2228 0: case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break;
2229 0: case BuiltinType::Short: ID = pch::PREDEF_TYPE_SHORT_ID; break;
2230 472: case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break;
2231 2: case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break;
2232 0: case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break;
2233 7: case BuiltinType::Int128: ID = pch::PREDEF_TYPE_INT128_ID; break;
2234 79: case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break;
2235 57: case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break;
2236 0: case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
2237 2: case BuiltinType::NullPtr: ID = pch::PREDEF_TYPE_NULLPTR_ID; break;
2238 0: case BuiltinType::Char16: ID = pch::PREDEF_TYPE_CHAR16_ID; break;
2239 0: case BuiltinType::Char32: ID = pch::PREDEF_TYPE_CHAR32_ID; break;
2240 0: case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break;
2241 0: case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
2242 15: case BuiltinType::ObjCId: ID = pch::PREDEF_TYPE_OBJC_ID; break;
2243 10: case BuiltinType::ObjCClass: ID = pch::PREDEF_TYPE_OBJC_CLASS; break;
2244 10: case BuiltinType::ObjCSel: ID = pch::PREDEF_TYPE_OBJC_SEL; break;
2245 : case BuiltinType::UndeducedAuto:
2246 0: assert(0 && "Should not see undeduced auto here");
2247 : break;
2248 : }
2249 :
2250 826: Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
2251 826: return;
2252 : }
2253 :
2254 862: pch::TypeID &ID = TypeIDs[T];
372: branch 0 taken
490: branch 1 taken
2255 862: if (ID == 0) {
2256 : // We haven't seen this type before. Assign it a new ID and put it
2257 : // into the queue of types to emit.
2258 372: ID = NextTypeID++;
2259 372: DeclTypesToEmit.push(T);
2260 : }
2261 :
2262 : // Encode the type qualifiers in the type reference.
2263 862: Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
2264 : }
2265 :
2266 2660: void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
458: branch 0 taken
2202: branch 1 taken
2267 2660: if (D == 0) {
2268 458: Record.push_back(0);
2269 458: return;
2270 : }
2271 :
2272 2202: pch::DeclID &ID = DeclIDs[D];
558: branch 0 taken
1644: branch 1 taken
2273 2202: if (ID == 0) {
2274 : // We haven't seen this declaration before. Give it a new ID and
2275 : // enqueue it in the list of declarations to emit.
2276 558: ID = DeclIDs.size();
2277 558: DeclTypesToEmit.push(const_cast<Decl *>(D));
2278 : }
2279 :
2280 2202: Record.push_back(ID);
2281 : }
2282 :
2283 345: pch::DeclID PCHWriter::getDeclID(const Decl *D) {
0: branch 0 not taken
345: branch 1 taken
2284 345: if (D == 0)
2285 0: return 0;
2286 :
345: branch 4 taken
0: branch 5 not taken
2287 345: assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!");
2288 345: return DeclIDs[D];
2289 : }
2290 :
2291 664: void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
2292 : // FIXME: Emit a stable enum for NameKind. 0 = Identifier etc.
2293 664: Record.push_back(Name.getNameKind());
571: branch 1 taken
62: branch 2 taken
20: branch 3 taken
11: branch 4 taken
0: branch 5 not taken
0: branch 6 not taken
2294 664: switch (Name.getNameKind()) {
2295 : case DeclarationName::Identifier:
2296 571: AddIdentifierRef(Name.getAsIdentifierInfo(), Record);
2297 571: break;
2298 :
2299 : case DeclarationName::ObjCZeroArgSelector:
2300 : case DeclarationName::ObjCOneArgSelector:
2301 : case DeclarationName::ObjCMultiArgSelector:
2302 62: AddSelectorRef(Name.getObjCSelector(), Record);
2303 62: break;
2304 :
2305 : case DeclarationName::CXXConstructorName:
2306 : case DeclarationName::CXXDestructorName:
2307 : case DeclarationName::CXXConversionFunctionName:
2308 20: AddTypeRef(Name.getCXXNameType(), Record);
2309 20: break;
2310 :
2311 : case DeclarationName::CXXOperatorName:
2312 11: Record.push_back(Name.getCXXOverloadedOperator());
2313 11: break;
2314 :
2315 : case DeclarationName::CXXLiteralOperatorName:
2316 0: AddIdentifierRef(Name.getCXXLiteralIdentifier(), Record);
2317 : break;
2318 :
2319 : case DeclarationName::CXXUsingDirective:
2320 : // No extra data to emit
2321 : break;
2322 : }
2323 664: }
2324 :
Generated: 2010-02-10 01:31 by zcov