blob: d366cddf175bb6d4ac672e109de6288b9882b919 [file] [log] [blame]
Douglas Gregorc34897d2009-04-09 22:27:44 +00001//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- 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 PCHReader class, which reads a precompiled header.
11//
12//===----------------------------------------------------------------------===//
13#include "clang/Frontend/PCHReader.h"
14#include "clang/Frontend/PCHBitCodes.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/Type.h"
18#include "llvm/Bitcode/BitstreamReader.h"
19#include "llvm/Support/Compiler.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include <algorithm>
22#include <cstdio>
23
24using namespace clang;
25
26//===----------------------------------------------------------------------===//
27// Declaration deserialization
28//===----------------------------------------------------------------------===//
29namespace {
30 class VISIBILITY_HIDDEN PCHDeclReader {
31 PCHReader &Reader;
32 const PCHReader::RecordData &Record;
33 unsigned &Idx;
34
35 public:
36 PCHDeclReader(PCHReader &Reader, const PCHReader::RecordData &Record,
37 unsigned &Idx)
38 : Reader(Reader), Record(Record), Idx(Idx) { }
39
40 void VisitDecl(Decl *D);
41 void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
42 void VisitNamedDecl(NamedDecl *ND);
43 void VisitTypeDecl(TypeDecl *TD);
44 void VisitTypedefDecl(TypedefDecl *TD);
45 void VisitValueDecl(ValueDecl *VD);
46 void VisitVarDecl(VarDecl *VD);
47
48 std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
49 };
50}
51
52void PCHDeclReader::VisitDecl(Decl *D) {
53 D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
54 D->setLexicalDeclContext(
55 cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
56 D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
57 D->setInvalidDecl(Record[Idx++]);
58 // FIXME: hasAttrs
59 D->setImplicit(Record[Idx++]);
60 D->setAccess((AccessSpecifier)Record[Idx++]);
61}
62
63void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
64 VisitDecl(TU);
65}
66
67void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
68 VisitDecl(ND);
69 ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
70}
71
72void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
73 VisitNamedDecl(TD);
74 // FIXME: circular dependencies here?
75 TD->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
76}
77
78void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
79 VisitTypeDecl(TD);
80 TD->setUnderlyingType(Reader.GetType(Record[Idx++]));
81}
82
83void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
84 VisitNamedDecl(VD);
85 VD->setType(Reader.GetType(Record[Idx++]));
86}
87
88void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
89 VisitValueDecl(VD);
90 VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
91 VD->setThreadSpecified(Record[Idx++]);
92 VD->setCXXDirectInitializer(Record[Idx++]);
93 VD->setDeclaredInCondition(Record[Idx++]);
94 VD->setPreviousDeclaration(
95 cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
96 VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
97}
98
99std::pair<uint64_t, uint64_t>
100PCHDeclReader::VisitDeclContext(DeclContext *DC) {
101 uint64_t LexicalOffset = Record[Idx++];
102 uint64_t VisibleOffset = 0;
103 if (DC->getPrimaryContext() == DC)
104 VisibleOffset = Record[Idx++];
105 return std::make_pair(LexicalOffset, VisibleOffset);
106}
107
108// FIXME: use the diagnostics machinery
109static bool Error(const char *Str) {
110 std::fprintf(stderr, "%s\n", Str);
111 return true;
112}
113
114/// \brief Read the type-offsets block.
115bool PCHReader::ReadTypeOffsets() {
116 if (Stream.EnterSubBlock(pch::TYPE_OFFSETS_BLOCK_ID))
117 return Error("Malformed block record");
118
119 RecordData Record;
120 while (true) {
121 unsigned Code = Stream.ReadCode();
122 if (Code == llvm::bitc::END_BLOCK) {
123 if (Stream.ReadBlockEnd())
124 return Error("Error at end of TYPE_OFFSETS block");
125 return false;
126 }
127
128 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
129 // No known subblocks, always skip them.
130 Stream.ReadSubBlockID();
131 if (Stream.SkipBlock())
132 return Error("Malformed block record");
133 continue;
134 }
135
136 if (Code == llvm::bitc::DEFINE_ABBREV) {
137 Stream.ReadAbbrevRecord();
138 continue;
139 }
140
141 // Read a record.
142 Record.clear();
143 switch (Stream.ReadRecord(Code, Record)) {
144 default: // Default behavior: ignore.
145 break;
146 case pch::TYPE_OFFSET:
147 if (!TypeOffsets.empty())
148 return Error("Duplicate TYPE_OFFSETS block");
149 TypeOffsets.swap(Record);
150 TypeAlreadyLoaded.resize(TypeOffsets.size(), false);
151 break;
152 }
153 }
154}
155
156/// \brief Read the decl-offsets block.
157bool PCHReader::ReadDeclOffsets() {
158 if (Stream.EnterSubBlock(pch::DECL_OFFSETS_BLOCK_ID))
159 return Error("Malformed block record");
160
161 RecordData Record;
162 while (true) {
163 unsigned Code = Stream.ReadCode();
164 if (Code == llvm::bitc::END_BLOCK) {
165 if (Stream.ReadBlockEnd())
166 return Error("Error at end of DECL_OFFSETS block");
167 return false;
168 }
169
170 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
171 // No known subblocks, always skip them.
172 Stream.ReadSubBlockID();
173 if (Stream.SkipBlock())
174 return Error("Malformed block record");
175 continue;
176 }
177
178 if (Code == llvm::bitc::DEFINE_ABBREV) {
179 Stream.ReadAbbrevRecord();
180 continue;
181 }
182
183 // Read a record.
184 Record.clear();
185 switch (Stream.ReadRecord(Code, Record)) {
186 default: // Default behavior: ignore.
187 break;
188 case pch::DECL_OFFSET:
189 if (!DeclOffsets.empty())
190 return Error("Duplicate DECL_OFFSETS block");
191 DeclOffsets.swap(Record);
192 DeclAlreadyLoaded.resize(DeclOffsets.size(), false);
193 break;
194 }
195 }
196}
197
198bool PCHReader::ReadPCHBlock() {
199 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID))
200 return Error("Malformed block record");
201
202 // Read all of the records and blocks for the PCH file.
203 while (!Stream.AtEndOfStream()) {
204 unsigned Code = Stream.ReadCode();
205 if (Code == llvm::bitc::END_BLOCK) {
206 if (Stream.ReadBlockEnd())
207 return Error("Error at end of module block");
208 return false;
209 }
210
211 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
212 switch (Stream.ReadSubBlockID()) {
213 case pch::DECLS_BLOCK_ID: // Skip decls block (lazily loaded)
214 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
215 default: // Skip unknown content.
216 if (Stream.SkipBlock())
217 return Error("Malformed block record");
218 break;
219
220
221 case pch::TYPE_OFFSETS_BLOCK_ID:
222 if (ReadTypeOffsets())
223 return Error("Malformed type-offsets block");
224 break;
225
226 case pch::DECL_OFFSETS_BLOCK_ID:
227 if (ReadDeclOffsets())
228 return Error("Malformed decl-offsets block");
229 break;
230 }
231 }
232 }
233
234 return Error("Premature end of bitstream");
235}
236
237PCHReader::~PCHReader() { }
238
239bool PCHReader::ReadPCH(const std::string &FileName) {
240 // Open the PCH file.
241 std::string ErrStr;
242 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
243 if (!Buffer)
244 return Error(ErrStr.c_str());
245
246 // Initialize the stream
247 Stream.init((const unsigned char *)Buffer->getBufferStart(),
248 (const unsigned char *)Buffer->getBufferEnd());
249
250 // Sniff for the signature.
251 if (Stream.Read(8) != 'C' ||
252 Stream.Read(8) != 'P' ||
253 Stream.Read(8) != 'C' ||
254 Stream.Read(8) != 'H')
255 return Error("Not a PCH file");
256
257 // We expect a number of well-defined blocks, though we don't necessarily
258 // need to understand them all.
259 while (!Stream.AtEndOfStream()) {
260 unsigned Code = Stream.ReadCode();
261
262 if (Code != llvm::bitc::ENTER_SUBBLOCK)
263 return Error("Invalid record at top-level");
264
265 unsigned BlockID = Stream.ReadSubBlockID();
266
267 // We only know the PCH subblock ID.
268 switch (BlockID) {
269 case llvm::bitc::BLOCKINFO_BLOCK_ID:
270 if (Stream.ReadBlockInfoBlock())
271 return Error("Malformed BlockInfoBlock");
272 break;
273 case pch::PCH_BLOCK_ID:
274 if (ReadPCHBlock())
275 return true;
276 break;
277 default:
278 if (Stream.SkipBlock())
279 return Error("Malformed block record");
280 break;
281 }
282 }
283
284 // Load the translation unit declaration
285 ReadDeclRecord(DeclOffsets[0], 0);
286
287 return false;
288}
289
290/// \brief Read and return the type at the given offset.
291///
292/// This routine actually reads the record corresponding to the type
293/// at the given offset in the bitstream. It is a helper routine for
294/// GetType, which deals with reading type IDs.
295QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
296 Stream.JumpToBit(Offset);
297 RecordData Record;
298 unsigned Code = Stream.ReadCode();
299 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
300 case pch::TYPE_FIXED_WIDTH_INT: {
301 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
302 return Context.getFixedWidthIntType(Record[0], Record[1]);
303 }
304
305 case pch::TYPE_COMPLEX: {
306 assert(Record.size() == 1 && "Incorrect encoding of complex type");
307 QualType ElemType = GetType(Record[0]);
308 return Context.getComplexType(ElemType);
309 }
310
311 case pch::TYPE_POINTER: {
312 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
313 QualType PointeeType = GetType(Record[0]);
314 return Context.getPointerType(PointeeType);
315 }
316
317 case pch::TYPE_BLOCK_POINTER: {
318 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
319 QualType PointeeType = GetType(Record[0]);
320 return Context.getBlockPointerType(PointeeType);
321 }
322
323 case pch::TYPE_LVALUE_REFERENCE: {
324 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
325 QualType PointeeType = GetType(Record[0]);
326 return Context.getLValueReferenceType(PointeeType);
327 }
328
329 case pch::TYPE_RVALUE_REFERENCE: {
330 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
331 QualType PointeeType = GetType(Record[0]);
332 return Context.getRValueReferenceType(PointeeType);
333 }
334
335 case pch::TYPE_MEMBER_POINTER: {
336 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
337 QualType PointeeType = GetType(Record[0]);
338 QualType ClassType = GetType(Record[1]);
339 return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
340 }
341
342 // FIXME: Several other kinds of types to deserialize here!
343 default:
344 assert("Unable to deserialize this type");
345 break;
346 }
347
348 // Suppress a GCC warning
349 return QualType();
350}
351
352/// \brief Note that we have loaded the declaration with the given
353/// Index.
354///
355/// This routine notes that this declaration has already been loaded,
356/// so that future GetDecl calls will return this declaration rather
357/// than trying to load a new declaration.
358inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
359 assert(!DeclAlreadyLoaded[Index] && "Decl loaded twice?");
360 DeclAlreadyLoaded[Index] = true;
361 DeclOffsets[Index] = reinterpret_cast<uint64_t>(D);
362}
363
364/// \brief Read the declaration at the given offset from the PCH file.
365Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
366 Decl *D = 0;
367 Stream.JumpToBit(Offset);
368 RecordData Record;
369 unsigned Code = Stream.ReadCode();
370 unsigned Idx = 0;
371 PCHDeclReader Reader(*this, Record, Idx);
372 switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
373 case pch::DECL_TRANSLATION_UNIT:
374 assert(Index == 0 && "Translation unit must be at index 0");
375 Reader.VisitTranslationUnitDecl(Context.getTranslationUnitDecl());
376 D = Context.getTranslationUnitDecl();
377 LoadedDecl(Index, D);
378 break;
379
380 case pch::DECL_TYPEDEF: {
381 TypedefDecl *Typedef = TypedefDecl::Create(Context, 0, SourceLocation(),
382 0, QualType());
383 LoadedDecl(Index, Typedef);
384 Reader.VisitTypedefDecl(Typedef);
385 D = Typedef;
386 break;
387 }
388
389 case pch::DECL_VAR: {
390 VarDecl *Var = VarDecl::Create(Context, 0, SourceLocation(), 0, QualType(),
391 VarDecl::None, SourceLocation());
392 LoadedDecl(Index, Var);
393 Reader.VisitVarDecl(Var);
394 D = Var;
395 break;
396 }
397
398 default:
399 assert(false && "Cannot de-serialize this kind of declaration");
400 break;
401 }
402
403 // If this declaration is also a declaration context, get the
404 // offsets for its tables of lexical and visible declarations.
405 if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
406 std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
407 if (Offsets.first || Offsets.second) {
408 DC->setHasExternalLexicalStorage(Offsets.first != 0);
409 DC->setHasExternalVisibleStorage(Offsets.second != 0);
410 DeclContextOffsets[DC] = Offsets;
411 }
412 }
413 assert(Idx == Record.size());
414
415 return D;
416}
417
418QualType PCHReader::GetType(unsigned ID) {
419 unsigned Quals = ID & 0x07;
420 unsigned Index = ID >> 3;
421
422 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
423 QualType T;
424 switch ((pch::PredefinedTypeIDs)Index) {
425 case pch::PREDEF_TYPE_NULL_ID: return QualType();
426 case pch::PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
427 case pch::PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
428
429 case pch::PREDEF_TYPE_CHAR_U_ID:
430 case pch::PREDEF_TYPE_CHAR_S_ID:
431 // FIXME: Check that the signedness of CharTy is correct!
432 T = Context.CharTy;
433 break;
434
435 case pch::PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
436 case pch::PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
437 case pch::PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
438 case pch::PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
439 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
440 case pch::PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
441 case pch::PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
442 case pch::PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
443 case pch::PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
444 case pch::PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
445 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
446 case pch::PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
447 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
448 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
449 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
450 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
451 }
452
453 assert(!T.isNull() && "Unknown predefined type");
454 return T.getQualifiedType(Quals);
455 }
456
457 Index -= pch::NUM_PREDEF_TYPE_IDS;
458 if (!TypeAlreadyLoaded[Index]) {
459 // Load the type from the PCH file.
460 TypeOffsets[Index] = reinterpret_cast<uint64_t>(
461 ReadTypeRecord(TypeOffsets[Index]).getTypePtr());
462 TypeAlreadyLoaded[Index] = true;
463 }
464
465 return QualType(reinterpret_cast<Type *>(TypeOffsets[Index]), Quals);
466}
467
468Decl *PCHReader::GetDecl(unsigned ID) {
469 if (ID == 0)
470 return 0;
471
472 unsigned Index = ID - 1;
473 if (DeclAlreadyLoaded[Index])
474 return reinterpret_cast<Decl *>(DeclOffsets[Index]);
475
476 // Load the declaration from the PCH file.
477 return ReadDeclRecord(DeclOffsets[Index], Index);
478}
479
480bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
481 llvm::SmallVectorImpl<unsigned> &Decls) {
482 assert(DC->hasExternalLexicalStorage() &&
483 "DeclContext has no lexical decls in storage");
484 uint64_t Offset = DeclContextOffsets[DC].first;
485 assert(Offset && "DeclContext has no lexical decls in storage");
486
487 // Load the record containing all of the declarations lexically in
488 // this context.
489 Stream.JumpToBit(Offset);
490 RecordData Record;
491 unsigned Code = Stream.ReadCode();
492 unsigned RecCode = Stream.ReadRecord(Code, Record);
493 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
494
495 // Load all of the declaration IDs
496 Decls.clear();
497 Decls.insert(Decls.end(), Record.begin(), Record.end());
498 return false;
499}
500
501bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
502 llvm::SmallVectorImpl<VisibleDeclaration> & Decls) {
503 assert(DC->hasExternalVisibleStorage() &&
504 "DeclContext has no visible decls in storage");
505 uint64_t Offset = DeclContextOffsets[DC].second;
506 assert(Offset && "DeclContext has no visible decls in storage");
507
508 // Load the record containing all of the declarations visible in
509 // this context.
510 Stream.JumpToBit(Offset);
511 RecordData Record;
512 unsigned Code = Stream.ReadCode();
513 unsigned RecCode = Stream.ReadRecord(Code, Record);
514 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
515 if (Record.size() == 0)
516 return false;
517
518 Decls.clear();
519
520 unsigned Idx = 0;
521 // llvm::SmallVector<uintptr_t, 16> DeclIDs;
522 while (Idx < Record.size()) {
523 Decls.push_back(VisibleDeclaration());
524 Decls.back().Name = ReadDeclarationName(Record, Idx);
525
526 // FIXME: Don't actually read anything here!
527 unsigned Size = Record[Idx++];
528 llvm::SmallVector<unsigned, 4> & LoadedDecls
529 = Decls.back().Declarations;
530 LoadedDecls.reserve(Size);
531 for (unsigned I = 0; I < Size; ++I)
532 LoadedDecls.push_back(Record[Idx++]);
533 }
534
535 return false;
536}
537
538void PCHReader::PrintStats() {
539 std::fprintf(stderr, "*** PCH Statistics:\n");
540
541 unsigned NumTypesLoaded = std::count(TypeAlreadyLoaded.begin(),
542 TypeAlreadyLoaded.end(),
543 true);
544 unsigned NumDeclsLoaded = std::count(DeclAlreadyLoaded.begin(),
545 DeclAlreadyLoaded.end(),
546 true);
547 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
548 NumTypesLoaded, (unsigned)TypeAlreadyLoaded.size(),
549 ((float)NumTypesLoaded/(float)TypeAlreadyLoaded.size() * 100));
550 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
551 NumDeclsLoaded, (unsigned)DeclAlreadyLoaded.size(),
552 ((float)NumDeclsLoaded/(float)DeclAlreadyLoaded.size() * 100));
553 std::fprintf(stderr, "\n");
554}
555
556const IdentifierInfo *PCHReader::GetIdentifierInfo(const RecordData &Record,
557 unsigned &Idx) {
558 // FIXME: we need unique IDs for identifiers.
559 std::string Str;
560 unsigned Length = Record[Idx++];
561 Str.resize(Length);
562 for (unsigned I = 0; I != Length; ++I)
563 Str[I] = Record[Idx++];
564 return &Context.Idents.get(Str);
565}
566
567DeclarationName
568PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
569 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
570 switch (Kind) {
571 case DeclarationName::Identifier:
572 return DeclarationName(GetIdentifierInfo(Record, Idx));
573
574 case DeclarationName::ObjCZeroArgSelector:
575 case DeclarationName::ObjCOneArgSelector:
576 case DeclarationName::ObjCMultiArgSelector:
577 assert(false && "Unable to de-serialize Objective-C selectors");
578 break;
579
580 case DeclarationName::CXXConstructorName:
581 return Context.DeclarationNames.getCXXConstructorName(
582 GetType(Record[Idx++]));
583
584 case DeclarationName::CXXDestructorName:
585 return Context.DeclarationNames.getCXXDestructorName(
586 GetType(Record[Idx++]));
587
588 case DeclarationName::CXXConversionFunctionName:
589 return Context.DeclarationNames.getCXXConversionFunctionName(
590 GetType(Record[Idx++]));
591
592 case DeclarationName::CXXOperatorName:
593 return Context.DeclarationNames.getCXXOperatorName(
594 (OverloadedOperatorKind)Record[Idx++]);
595
596 case DeclarationName::CXXUsingDirective:
597 return DeclarationName::getUsingDirectiveName();
598 }
599
600 // Required to silence GCC warning
601 return DeclarationName();
602}