blob: d044fee428069bd88eb6035c5c313f1d9d61c81a [file] [log] [blame]
Douglas Gregor2cf26342009-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//===----------------------------------------------------------------------===//
Chris Lattner4c6f9522009-04-27 05:14:47 +000013
Douglas Gregor2cf26342009-04-09 22:27:44 +000014#include "clang/Frontend/PCHReader.h"
Douglas Gregor0a0428e2009-04-10 20:39:37 +000015#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000016#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
Douglas Gregorfdd01722009-04-14 00:24:19 +000017#include "clang/AST/ASTConsumer.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000018#include "clang/AST/ASTContext.h"
Douglas Gregor0b748912009-04-14 21:18:50 +000019#include "clang/AST/Expr.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000020#include "clang/AST/Type.h"
Chris Lattner42d42b52009-04-10 21:41:48 +000021#include "clang/Lex/MacroInfo.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000022#include "clang/Lex/Preprocessor.h"
Steve Naroff83d63c72009-04-24 20:03:17 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000024#include "clang/Basic/OnDiskHashTable.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000025#include "clang/Basic/SourceManager.h"
Douglas Gregorbd945002009-04-13 16:31:14 +000026#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000027#include "clang/Basic/FileManager.h"
Douglas Gregor2bec0412009-04-10 21:16:55 +000028#include "clang/Basic/TargetInfo.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000029#include "llvm/Bitcode/BitstreamReader.h"
30#include "llvm/Support/Compiler.h"
31#include "llvm/Support/MemoryBuffer.h"
32#include <algorithm>
33#include <cstdio>
Douglas Gregor4fed3f42009-04-27 18:38:38 +000034#include <sys/stat.h>
Douglas Gregor2cf26342009-04-09 22:27:44 +000035using namespace clang;
36
37//===----------------------------------------------------------------------===//
Douglas Gregor668c1a42009-04-21 22:25:48 +000038// PCH reader implementation
39//===----------------------------------------------------------------------===//
40
Chris Lattner4c6f9522009-04-27 05:14:47 +000041PCHReader::PCHReader(Preprocessor &PP, ASTContext &Context)
42 : SemaObj(0), PP(PP), Context(Context), Consumer(0),
43 IdentifierTableData(0), IdentifierLookupTable(0),
44 IdentifierOffsets(0),
45 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
46 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregor4fed3f42009-04-27 18:38:38 +000047 TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
48 NumSLocEntriesRead(0), NumStatementsRead(0),
Douglas Gregor7f94b0b2009-04-27 06:38:32 +000049 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Chris Lattner4c6f9522009-04-27 05:14:47 +000050 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
51
52PCHReader::~PCHReader() {}
53
Chris Lattnerda930612009-04-27 05:58:23 +000054Expr *PCHReader::ReadDeclExpr() {
55 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
56}
57
58Expr *PCHReader::ReadTypeExpr() {
Chris Lattner52e97d12009-04-27 05:41:06 +000059 return dyn_cast_or_null<Expr>(ReadStmt(Stream));
Chris Lattner4c6f9522009-04-27 05:14:47 +000060}
61
62
Douglas Gregor668c1a42009-04-21 22:25:48 +000063namespace {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +000064class VISIBILITY_HIDDEN PCHMethodPoolLookupTrait {
65 PCHReader &Reader;
66
67public:
68 typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
69
70 typedef Selector external_key_type;
71 typedef external_key_type internal_key_type;
72
73 explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { }
74
75 static bool EqualKey(const internal_key_type& a,
76 const internal_key_type& b) {
77 return a == b;
78 }
79
80 static unsigned ComputeHash(Selector Sel) {
81 unsigned N = Sel.getNumArgs();
82 if (N == 0)
83 ++N;
84 unsigned R = 5381;
85 for (unsigned I = 0; I != N; ++I)
86 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
87 R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R);
88 return R;
89 }
90
91 // This hopefully will just get inlined and removed by the optimizer.
92 static const internal_key_type&
93 GetInternalKey(const external_key_type& x) { return x; }
94
95 static std::pair<unsigned, unsigned>
96 ReadKeyDataLength(const unsigned char*& d) {
97 using namespace clang::io;
98 unsigned KeyLen = ReadUnalignedLE16(d);
99 unsigned DataLen = ReadUnalignedLE16(d);
100 return std::make_pair(KeyLen, DataLen);
101 }
102
Douglas Gregor83941df2009-04-25 17:48:32 +0000103 internal_key_type ReadKey(const unsigned char* d, unsigned) {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000104 using namespace clang::io;
105 SelectorTable &SelTable = Reader.getContext().Selectors;
106 unsigned N = ReadUnalignedLE16(d);
107 IdentifierInfo *FirstII
108 = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
109 if (N == 0)
110 return SelTable.getNullarySelector(FirstII);
111 else if (N == 1)
112 return SelTable.getUnarySelector(FirstII);
113
114 llvm::SmallVector<IdentifierInfo *, 16> Args;
115 Args.push_back(FirstII);
116 for (unsigned I = 1; I != N; ++I)
117 Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
118
119 return SelTable.getSelector(N, &Args[0]);
120 }
121
122 data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
123 using namespace clang::io;
124 unsigned NumInstanceMethods = ReadUnalignedLE16(d);
125 unsigned NumFactoryMethods = ReadUnalignedLE16(d);
126
127 data_type Result;
128
129 // Load instance methods
130 ObjCMethodList *Prev = 0;
131 for (unsigned I = 0; I != NumInstanceMethods; ++I) {
132 ObjCMethodDecl *Method
133 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
134 if (!Result.first.Method) {
135 // This is the first method, which is the easy case.
136 Result.first.Method = Method;
137 Prev = &Result.first;
138 continue;
139 }
140
141 Prev->Next = new ObjCMethodList(Method, 0);
142 Prev = Prev->Next;
143 }
144
145 // Load factory methods
146 Prev = 0;
147 for (unsigned I = 0; I != NumFactoryMethods; ++I) {
148 ObjCMethodDecl *Method
149 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
150 if (!Result.second.Method) {
151 // This is the first method, which is the easy case.
152 Result.second.Method = Method;
153 Prev = &Result.second;
154 continue;
155 }
156
157 Prev->Next = new ObjCMethodList(Method, 0);
158 Prev = Prev->Next;
159 }
160
161 return Result;
162 }
163};
164
165} // end anonymous namespace
166
167/// \brief The on-disk hash table used for the global method pool.
168typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait>
169 PCHMethodPoolLookupTable;
170
171namespace {
Douglas Gregor668c1a42009-04-21 22:25:48 +0000172class VISIBILITY_HIDDEN PCHIdentifierLookupTrait {
173 PCHReader &Reader;
174
175 // If we know the IdentifierInfo in advance, it is here and we will
176 // not build a new one. Used when deserializing information about an
177 // identifier that was constructed before the PCH file was read.
178 IdentifierInfo *KnownII;
179
180public:
181 typedef IdentifierInfo * data_type;
182
183 typedef const std::pair<const char*, unsigned> external_key_type;
184
185 typedef external_key_type internal_key_type;
186
187 explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0)
188 : Reader(Reader), KnownII(II) { }
189
190 static bool EqualKey(const internal_key_type& a,
191 const internal_key_type& b) {
192 return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
193 : false;
194 }
195
196 static unsigned ComputeHash(const internal_key_type& a) {
197 return BernsteinHash(a.first, a.second);
198 }
199
200 // This hopefully will just get inlined and removed by the optimizer.
201 static const internal_key_type&
202 GetInternalKey(const external_key_type& x) { return x; }
203
204 static std::pair<unsigned, unsigned>
205 ReadKeyDataLength(const unsigned char*& d) {
206 using namespace clang::io;
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000207 unsigned DataLen = ReadUnalignedLE16(d);
Douglas Gregord6595a42009-04-25 21:04:17 +0000208 unsigned KeyLen = ReadUnalignedLE16(d);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000209 return std::make_pair(KeyLen, DataLen);
210 }
211
212 static std::pair<const char*, unsigned>
213 ReadKey(const unsigned char* d, unsigned n) {
214 assert(n >= 2 && d[n-1] == '\0');
215 return std::make_pair((const char*) d, n-1);
216 }
217
218 IdentifierInfo *ReadData(const internal_key_type& k,
219 const unsigned char* d,
220 unsigned DataLen) {
221 using namespace clang::io;
Douglas Gregor6cfc1a82009-04-22 21:15:06 +0000222 uint32_t Bits = ReadUnalignedLE32(d);
Douglas Gregor2deaea32009-04-22 18:49:13 +0000223 bool CPlusPlusOperatorKeyword = Bits & 0x01;
224 Bits >>= 1;
225 bool Poisoned = Bits & 0x01;
226 Bits >>= 1;
227 bool ExtensionToken = Bits & 0x01;
228 Bits >>= 1;
229 bool hasMacroDefinition = Bits & 0x01;
230 Bits >>= 1;
231 unsigned ObjCOrBuiltinID = Bits & 0x3FF;
232 Bits >>= 10;
233 unsigned TokenID = Bits & 0xFF;
234 Bits >>= 8;
235
Douglas Gregor668c1a42009-04-21 22:25:48 +0000236 pch::IdentID ID = ReadUnalignedLE32(d);
Douglas Gregor2deaea32009-04-22 18:49:13 +0000237 assert(Bits == 0 && "Extra bits in the identifier?");
Douglas Gregor668c1a42009-04-21 22:25:48 +0000238 DataLen -= 8;
239
240 // Build the IdentifierInfo itself and link the identifier ID with
241 // the new IdentifierInfo.
242 IdentifierInfo *II = KnownII;
243 if (!II)
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000244 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
245 k.first, k.first + k.second);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000246 Reader.SetIdentifierInfo(ID, II);
247
Douglas Gregor2deaea32009-04-22 18:49:13 +0000248 // Set or check the various bits in the IdentifierInfo structure.
249 // FIXME: Load token IDs lazily, too?
250 assert((unsigned)II->getTokenID() == TokenID &&
251 "Incorrect token ID loaded");
252 (void)TokenID;
253 II->setObjCOrBuiltinID(ObjCOrBuiltinID);
254 assert(II->isExtensionToken() == ExtensionToken &&
255 "Incorrect extension token flag");
256 (void)ExtensionToken;
257 II->setIsPoisoned(Poisoned);
258 assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
259 "Incorrect C++ operator keyword flag");
260 (void)CPlusPlusOperatorKeyword;
261
Douglas Gregor37e26842009-04-21 23:56:24 +0000262 // If this identifier is a macro, deserialize the macro
263 // definition.
264 if (hasMacroDefinition) {
265 uint32_t Offset = ReadUnalignedLE64(d);
266 Reader.ReadMacroRecord(Offset);
267 DataLen -= 8;
268 }
Douglas Gregor668c1a42009-04-21 22:25:48 +0000269
270 // Read all of the declarations visible at global scope with this
271 // name.
272 Sema *SemaObj = Reader.getSema();
273 while (DataLen > 0) {
274 NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
Douglas Gregor668c1a42009-04-21 22:25:48 +0000275 if (SemaObj) {
276 // Introduce this declaration into the translation-unit scope
277 // and add it to the declaration chain for this identifier, so
278 // that (unqualified) name lookup will find it.
279 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
280 SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
281 } else {
282 // Queue this declaration so that it will be added to the
283 // translation unit scope and identifier's declaration chain
284 // once a Sema object is known.
Douglas Gregor6cfc1a82009-04-22 21:15:06 +0000285 Reader.PreloadedDecls.push_back(D);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000286 }
287
288 DataLen -= 4;
289 }
290 return II;
291 }
292};
293
294} // end anonymous namespace
295
296/// \brief The on-disk hash table used to contain information about
297/// all of the identifiers in the program.
298typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
299 PCHIdentifierLookupTable;
300
Douglas Gregor2cf26342009-04-09 22:27:44 +0000301// FIXME: use the diagnostics machinery
302static bool Error(const char *Str) {
303 std::fprintf(stderr, "%s\n", Str);
304 return true;
305}
306
Douglas Gregore1d918e2009-04-10 23:10:45 +0000307/// \brief Check the contents of the predefines buffer against the
308/// contents of the predefines buffer used to build the PCH file.
309///
310/// The contents of the two predefines buffers should be the same. If
311/// not, then some command-line option changed the preprocessor state
312/// and we must reject the PCH file.
313///
314/// \param PCHPredef The start of the predefines buffer in the PCH
315/// file.
316///
317/// \param PCHPredefLen The length of the predefines buffer in the PCH
318/// file.
319///
320/// \param PCHBufferID The FileID for the PCH predefines buffer.
321///
322/// \returns true if there was a mismatch (in which case the PCH file
323/// should be ignored), or false otherwise.
324bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
325 unsigned PCHPredefLen,
326 FileID PCHBufferID) {
327 const char *Predef = PP.getPredefines().c_str();
328 unsigned PredefLen = PP.getPredefines().size();
329
330 // If the two predefines buffers compare equal, we're done!.
331 if (PredefLen == PCHPredefLen &&
332 strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
333 return false;
334
335 // The predefines buffers are different. Produce a reasonable
336 // diagnostic showing where they are different.
337
338 // The source locations (potentially in the two different predefines
339 // buffers)
340 SourceLocation Loc1, Loc2;
341 SourceManager &SourceMgr = PP.getSourceManager();
342
343 // Create a source buffer for our predefines string, so
344 // that we can build a diagnostic that points into that
345 // source buffer.
346 FileID BufferID;
347 if (Predef && Predef[0]) {
348 llvm::MemoryBuffer *Buffer
349 = llvm::MemoryBuffer::getMemBuffer(Predef, Predef + PredefLen,
350 "<built-in>");
351 BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
352 }
353
354 unsigned MinLen = std::min(PredefLen, PCHPredefLen);
355 std::pair<const char *, const char *> Locations
356 = std::mismatch(Predef, Predef + MinLen, PCHPredef);
357
358 if (Locations.first != Predef + MinLen) {
359 // We found the location in the two buffers where there is a
360 // difference. Form source locations to point there (in both
361 // buffers).
362 unsigned Offset = Locations.first - Predef;
363 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
364 .getFileLocWithOffset(Offset);
365 Loc2 = SourceMgr.getLocForStartOfFile(PCHBufferID)
366 .getFileLocWithOffset(Offset);
367 } else if (PredefLen > PCHPredefLen) {
368 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
369 .getFileLocWithOffset(MinLen);
370 } else {
371 Loc1 = SourceMgr.getLocForStartOfFile(PCHBufferID)
372 .getFileLocWithOffset(MinLen);
373 }
374
375 Diag(Loc1, diag::warn_pch_preprocessor);
376 if (Loc2.isValid())
377 Diag(Loc2, diag::note_predef_in_pch);
378 Diag(diag::note_ignoring_pch) << FileName;
379 return true;
380}
381
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000382//===----------------------------------------------------------------------===//
383// Source Manager Deserialization
384//===----------------------------------------------------------------------===//
385
Douglas Gregorbd945002009-04-13 16:31:14 +0000386/// \brief Read the line table in the source manager block.
387/// \returns true if ther was an error.
388static bool ParseLineTable(SourceManager &SourceMgr,
389 llvm::SmallVectorImpl<uint64_t> &Record) {
390 unsigned Idx = 0;
391 LineTableInfo &LineTable = SourceMgr.getLineTable();
392
393 // Parse the file names
Douglas Gregorff0a9872009-04-13 17:12:42 +0000394 std::map<int, int> FileIDs;
395 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregorbd945002009-04-13 16:31:14 +0000396 // Extract the file name
397 unsigned FilenameLen = Record[Idx++];
398 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
399 Idx += FilenameLen;
Douglas Gregorff0a9872009-04-13 17:12:42 +0000400 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
401 Filename.size());
Douglas Gregorbd945002009-04-13 16:31:14 +0000402 }
403
404 // Parse the line entries
405 std::vector<LineEntry> Entries;
406 while (Idx < Record.size()) {
Douglas Gregorff0a9872009-04-13 17:12:42 +0000407 int FID = FileIDs[Record[Idx++]];
Douglas Gregorbd945002009-04-13 16:31:14 +0000408
409 // Extract the line entries
410 unsigned NumEntries = Record[Idx++];
411 Entries.clear();
412 Entries.reserve(NumEntries);
413 for (unsigned I = 0; I != NumEntries; ++I) {
414 unsigned FileOffset = Record[Idx++];
415 unsigned LineNo = Record[Idx++];
416 int FilenameID = Record[Idx++];
417 SrcMgr::CharacteristicKind FileKind
418 = (SrcMgr::CharacteristicKind)Record[Idx++];
419 unsigned IncludeOffset = Record[Idx++];
420 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
421 FileKind, IncludeOffset));
422 }
423 LineTable.AddEntry(FID, Entries);
424 }
425
426 return false;
427}
428
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000429namespace {
430
431class VISIBILITY_HIDDEN PCHStatData {
432public:
433 const bool hasStat;
434 const ino_t ino;
435 const dev_t dev;
436 const mode_t mode;
437 const time_t mtime;
438 const off_t size;
439
440 PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
441 : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
442
443 PCHStatData()
444 : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
445};
446
447class VISIBILITY_HIDDEN PCHStatLookupTrait {
448 public:
449 typedef const char *external_key_type;
450 typedef const char *internal_key_type;
451
452 typedef PCHStatData data_type;
453
454 static unsigned ComputeHash(const char *path) {
455 return BernsteinHash(path);
456 }
457
458 static internal_key_type GetInternalKey(const char *path) { return path; }
459
460 static bool EqualKey(internal_key_type a, internal_key_type b) {
461 return strcmp(a, b) == 0;
462 }
463
464 static std::pair<unsigned, unsigned>
465 ReadKeyDataLength(const unsigned char*& d) {
466 unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
467 unsigned DataLen = (unsigned) *d++;
468 return std::make_pair(KeyLen + 1, DataLen);
469 }
470
471 static internal_key_type ReadKey(const unsigned char *d, unsigned) {
472 return (const char *)d;
473 }
474
475 static data_type ReadData(const internal_key_type, const unsigned char *d,
476 unsigned /*DataLen*/) {
477 using namespace clang::io;
478
479 if (*d++ == 1)
480 return data_type();
481
482 ino_t ino = (ino_t) ReadUnalignedLE32(d);
483 dev_t dev = (dev_t) ReadUnalignedLE32(d);
484 mode_t mode = (mode_t) ReadUnalignedLE16(d);
485 time_t mtime = (time_t) ReadUnalignedLE64(d);
486 off_t size = (off_t) ReadUnalignedLE64(d);
487 return data_type(ino, dev, mode, mtime, size);
488 }
489};
490
491/// \brief stat() cache for precompiled headers.
492///
493/// This cache is very similar to the stat cache used by pretokenized
494/// headers.
495class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache {
496 typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
497 CacheTy *Cache;
498
499 unsigned &NumStatHits, &NumStatMisses;
500public:
501 PCHStatCache(const unsigned char *Buckets,
502 const unsigned char *Base,
503 unsigned &NumStatHits,
504 unsigned &NumStatMisses)
505 : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
506 Cache = CacheTy::Create(Buckets, Base);
507 }
508
509 ~PCHStatCache() { delete Cache; }
510
511 int stat(const char *path, struct stat *buf) {
512 // Do the lookup for the file's data in the PCH file.
513 CacheTy::iterator I = Cache->find(path);
514
515 // If we don't get a hit in the PCH file just forward to 'stat'.
516 if (I == Cache->end()) {
517 ++NumStatMisses;
518 return ::stat(path, buf);
519 }
520
521 ++NumStatHits;
522 PCHStatData Data = *I;
523
524 if (!Data.hasStat)
525 return 1;
526
527 buf->st_ino = Data.ino;
528 buf->st_dev = Data.dev;
529 buf->st_mtime = Data.mtime;
530 buf->st_mode = Data.mode;
531 buf->st_size = Data.size;
532 return 0;
533 }
534};
535} // end anonymous namespace
536
537
Douglas Gregor14f79002009-04-10 03:52:48 +0000538/// \brief Read the source manager block
Douglas Gregore1d918e2009-04-10 23:10:45 +0000539PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregor14f79002009-04-10 03:52:48 +0000540 using namespace SrcMgr;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000541
542 // Set the source-location entry cursor to the current position in
543 // the stream. This cursor will be used to read the contents of the
544 // source manager block initially, and then lazily read
545 // source-location entries as needed.
546 SLocEntryCursor = Stream;
547
548 // The stream itself is going to skip over the source manager block.
549 if (Stream.SkipBlock()) {
550 Error("Malformed block record");
551 return Failure;
552 }
553
554 // Enter the source manager block.
555 if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
Douglas Gregore1d918e2009-04-10 23:10:45 +0000556 Error("Malformed source manager block record");
557 return Failure;
558 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000559
560 SourceManager &SourceMgr = Context.getSourceManager();
561 RecordData Record;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000562 unsigned NumHeaderInfos = 0;
Douglas Gregor14f79002009-04-10 03:52:48 +0000563 while (true) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000564 unsigned Code = SLocEntryCursor.ReadCode();
Douglas Gregor14f79002009-04-10 03:52:48 +0000565 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000566 if (SLocEntryCursor.ReadBlockEnd()) {
Douglas Gregore1d918e2009-04-10 23:10:45 +0000567 Error("Error at end of Source Manager block");
568 return Failure;
569 }
Douglas Gregore1d918e2009-04-10 23:10:45 +0000570 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000571 }
572
573 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
574 // No known subblocks, always skip them.
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000575 SLocEntryCursor.ReadSubBlockID();
576 if (SLocEntryCursor.SkipBlock()) {
Douglas Gregore1d918e2009-04-10 23:10:45 +0000577 Error("Malformed block record");
578 return Failure;
579 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000580 continue;
581 }
582
583 if (Code == llvm::bitc::DEFINE_ABBREV) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000584 SLocEntryCursor.ReadAbbrevRecord();
Douglas Gregor14f79002009-04-10 03:52:48 +0000585 continue;
586 }
587
588 // Read a record.
589 const char *BlobStart;
590 unsigned BlobLen;
591 Record.clear();
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000592 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
Douglas Gregor14f79002009-04-10 03:52:48 +0000593 default: // Default behavior: ignore.
594 break;
595
Chris Lattner2c78b872009-04-14 23:22:57 +0000596 case pch::SM_LINE_TABLE:
Douglas Gregorbd945002009-04-13 16:31:14 +0000597 if (ParseLineTable(SourceMgr, Record))
598 return Failure;
Chris Lattner2c78b872009-04-14 23:22:57 +0000599 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000600
601 case pch::SM_HEADER_FILE_INFO: {
602 HeaderFileInfo HFI;
603 HFI.isImport = Record[0];
604 HFI.DirInfo = Record[1];
605 HFI.NumIncludes = Record[2];
606 HFI.ControllingMacroID = Record[3];
607 PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
608 break;
609 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000610
611 case pch::SM_SLOC_FILE_ENTRY:
612 case pch::SM_SLOC_BUFFER_ENTRY:
613 case pch::SM_SLOC_INSTANTIATION_ENTRY:
614 // Once we hit one of the source location entries, we're done.
615 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000616 }
617 }
618}
619
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000620/// \brief Read in the source location entry with the given ID.
621PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
622 if (ID == 0)
623 return Success;
624
625 if (ID > TotalNumSLocEntries) {
626 Error("source location entry ID out-of-range for PCH file");
627 return Failure;
628 }
629
630 ++NumSLocEntriesRead;
631 SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
632 unsigned Code = SLocEntryCursor.ReadCode();
633 if (Code == llvm::bitc::END_BLOCK ||
634 Code == llvm::bitc::ENTER_SUBBLOCK ||
635 Code == llvm::bitc::DEFINE_ABBREV) {
636 Error("incorrectly-formatted source location entry in PCH file");
637 return Failure;
638 }
639
640 SourceManager &SourceMgr = Context.getSourceManager();
641 RecordData Record;
642 const char *BlobStart;
643 unsigned BlobLen;
644 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
645 default:
646 Error("incorrectly-formatted source location entry in PCH file");
647 return Failure;
648
649 case pch::SM_SLOC_FILE_ENTRY: {
650 const FileEntry *File
651 = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
652 // FIXME: Error recovery if file cannot be found.
653 FileID FID = SourceMgr.createFileID(File,
654 SourceLocation::getFromRawEncoding(Record[1]),
655 (SrcMgr::CharacteristicKind)Record[2],
656 ID, Record[0]);
657 if (Record[3])
658 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
659 .setHasLineDirectives();
660
661 break;
662 }
663
664 case pch::SM_SLOC_BUFFER_ENTRY: {
665 const char *Name = BlobStart;
666 unsigned Offset = Record[0];
667 unsigned Code = SLocEntryCursor.ReadCode();
668 Record.clear();
669 unsigned RecCode
670 = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
671 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
672 (void)RecCode;
673 llvm::MemoryBuffer *Buffer
674 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
675 BlobStart + BlobLen - 1,
676 Name);
677 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
678
679 if (strcmp(Name, "<built-in>") == 0
680 && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID))
681 return IgnorePCH;
682
683 break;
684 }
685
686 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
687 SourceLocation SpellingLoc
688 = SourceLocation::getFromRawEncoding(Record[1]);
689 SourceMgr.createInstantiationLoc(SpellingLoc,
690 SourceLocation::getFromRawEncoding(Record[2]),
691 SourceLocation::getFromRawEncoding(Record[3]),
692 Record[4],
693 ID,
694 Record[0]);
695 break;
696 }
697 }
698
699 return Success;
700}
701
Chris Lattner6367f6d2009-04-27 01:05:14 +0000702/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
703/// specified cursor. Read the abbreviations that are at the top of the block
704/// and then leave the cursor pointing into the block.
705bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
706 unsigned BlockID) {
707 if (Cursor.EnterSubBlock(BlockID)) {
708 Error("Malformed block record");
709 return Failure;
710 }
711
Chris Lattner6367f6d2009-04-27 01:05:14 +0000712 while (true) {
713 unsigned Code = Cursor.ReadCode();
714
715 // We expect all abbrevs to be at the start of the block.
716 if (Code != llvm::bitc::DEFINE_ABBREV)
717 return false;
718 Cursor.ReadAbbrevRecord();
719 }
720}
721
Douglas Gregor37e26842009-04-21 23:56:24 +0000722void PCHReader::ReadMacroRecord(uint64_t Offset) {
723 // Keep track of where we are in the stream, then jump back there
724 // after reading this macro.
725 SavedStreamPosition SavedPosition(Stream);
726
727 Stream.JumpToBit(Offset);
728 RecordData Record;
729 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
730 MacroInfo *Macro = 0;
Steve Naroff83d63c72009-04-24 20:03:17 +0000731
Douglas Gregor37e26842009-04-21 23:56:24 +0000732 while (true) {
733 unsigned Code = Stream.ReadCode();
734 switch (Code) {
735 case llvm::bitc::END_BLOCK:
736 return;
737
738 case llvm::bitc::ENTER_SUBBLOCK:
739 // No known subblocks, always skip them.
740 Stream.ReadSubBlockID();
741 if (Stream.SkipBlock()) {
742 Error("Malformed block record");
743 return;
744 }
745 continue;
746
747 case llvm::bitc::DEFINE_ABBREV:
748 Stream.ReadAbbrevRecord();
749 continue;
750 default: break;
751 }
752
753 // Read a record.
754 Record.clear();
755 pch::PreprocessorRecordTypes RecType =
756 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
757 switch (RecType) {
Douglas Gregor37e26842009-04-21 23:56:24 +0000758 case pch::PP_MACRO_OBJECT_LIKE:
759 case pch::PP_MACRO_FUNCTION_LIKE: {
760 // If we already have a macro, that means that we've hit the end
761 // of the definition of the macro we were looking for. We're
762 // done.
763 if (Macro)
764 return;
765
766 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
767 if (II == 0) {
768 Error("Macro must have a name");
769 return;
770 }
771 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
772 bool isUsed = Record[2];
773
774 MacroInfo *MI = PP.AllocateMacroInfo(Loc);
775 MI->setIsUsed(isUsed);
776
777 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
778 // Decode function-like macro info.
779 bool isC99VarArgs = Record[3];
780 bool isGNUVarArgs = Record[4];
781 MacroArgs.clear();
782 unsigned NumArgs = Record[5];
783 for (unsigned i = 0; i != NumArgs; ++i)
784 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
785
786 // Install function-like macro info.
787 MI->setIsFunctionLike();
788 if (isC99VarArgs) MI->setIsC99Varargs();
789 if (isGNUVarArgs) MI->setIsGNUVarargs();
790 MI->setArgumentList(&MacroArgs[0], MacroArgs.size(),
791 PP.getPreprocessorAllocator());
792 }
793
794 // Finally, install the macro.
795 PP.setMacroInfo(II, MI);
796
797 // Remember that we saw this macro last so that we add the tokens that
798 // form its body to it.
799 Macro = MI;
800 ++NumMacrosRead;
801 break;
802 }
803
804 case pch::PP_TOKEN: {
805 // If we see a TOKEN before a PP_MACRO_*, then the file is
806 // erroneous, just pretend we didn't see this.
807 if (Macro == 0) break;
808
809 Token Tok;
810 Tok.startToken();
811 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
812 Tok.setLength(Record[1]);
813 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
814 Tok.setIdentifierInfo(II);
815 Tok.setKind((tok::TokenKind)Record[3]);
816 Tok.setFlag((Token::TokenFlags)Record[4]);
817 Macro->AddTokenToBody(Tok);
818 break;
819 }
Steve Naroff83d63c72009-04-24 20:03:17 +0000820 }
Douglas Gregor37e26842009-04-21 23:56:24 +0000821 }
822}
823
Douglas Gregor668c1a42009-04-21 22:25:48 +0000824PCHReader::PCHReadResult
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000825PCHReader::ReadPCHBlock() {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000826 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
827 Error("Malformed block record");
828 return Failure;
829 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000830
831 // Read all of the records and blocks for the PCH file.
Douglas Gregor8038d512009-04-10 17:25:41 +0000832 RecordData Record;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000833 while (!Stream.AtEndOfStream()) {
834 unsigned Code = Stream.ReadCode();
835 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000836 if (Stream.ReadBlockEnd()) {
837 Error("Error at end of module block");
838 return Failure;
839 }
Chris Lattner7356a312009-04-11 21:15:38 +0000840
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000841 return Success;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000842 }
843
844 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
845 switch (Stream.ReadSubBlockID()) {
Douglas Gregor2cf26342009-04-09 22:27:44 +0000846 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
847 default: // Skip unknown content.
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000848 if (Stream.SkipBlock()) {
849 Error("Malformed block record");
850 return Failure;
851 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000852 break;
853
Chris Lattner6367f6d2009-04-27 01:05:14 +0000854 case pch::DECLS_BLOCK_ID:
855 // We lazily load the decls block, but we want to set up the
856 // DeclsCursor cursor to point into it. Clone our current bitcode
857 // cursor to it, enter the block and read the abbrevs in that block.
858 // With the main cursor, we just skip over it.
859 DeclsCursor = Stream;
860 if (Stream.SkipBlock() || // Skip with the main cursor.
861 // Read the abbrevs.
862 ReadBlockAbbrevs(DeclsCursor, pch::DECLS_BLOCK_ID)) {
863 Error("Malformed block record");
864 return Failure;
865 }
866 break;
867
Chris Lattner7356a312009-04-11 21:15:38 +0000868 case pch::PREPROCESSOR_BLOCK_ID:
Chris Lattner7356a312009-04-11 21:15:38 +0000869 if (Stream.SkipBlock()) {
870 Error("Malformed block record");
871 return Failure;
872 }
873 break;
Steve Naroff90cd1bb2009-04-23 10:39:46 +0000874
Douglas Gregor14f79002009-04-10 03:52:48 +0000875 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +0000876 switch (ReadSourceManagerBlock()) {
877 case Success:
878 break;
879
880 case Failure:
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000881 Error("Malformed source manager block");
882 return Failure;
Douglas Gregore1d918e2009-04-10 23:10:45 +0000883
884 case IgnorePCH:
885 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000886 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000887 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000888 }
Douglas Gregor8038d512009-04-10 17:25:41 +0000889 continue;
890 }
891
892 if (Code == llvm::bitc::DEFINE_ABBREV) {
893 Stream.ReadAbbrevRecord();
894 continue;
895 }
896
897 // Read and process a record.
898 Record.clear();
Douglas Gregor2bec0412009-04-10 21:16:55 +0000899 const char *BlobStart = 0;
900 unsigned BlobLen = 0;
901 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
902 &BlobStart, &BlobLen)) {
Douglas Gregor8038d512009-04-10 17:25:41 +0000903 default: // Default behavior: ignore.
904 break;
905
906 case pch::TYPE_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +0000907 if (!TypesLoaded.empty()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000908 Error("Duplicate TYPE_OFFSET record in PCH file");
909 return Failure;
910 }
Chris Lattnerc732f5a2009-04-27 18:24:17 +0000911 TypeOffsets = (const uint32_t *)BlobStart;
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +0000912 TypesLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +0000913 break;
914
915 case pch::DECL_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +0000916 if (!DeclsLoaded.empty()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000917 Error("Duplicate DECL_OFFSET record in PCH file");
918 return Failure;
919 }
Chris Lattnerc732f5a2009-04-27 18:24:17 +0000920 DeclOffsets = (const uint32_t *)BlobStart;
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +0000921 DeclsLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +0000922 break;
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000923
924 case pch::LANGUAGE_OPTIONS:
925 if (ParseLanguageOptions(Record))
926 return IgnorePCH;
927 break;
Douglas Gregor2bec0412009-04-10 21:16:55 +0000928
Douglas Gregorafaf3082009-04-11 00:14:32 +0000929 case pch::TARGET_TRIPLE: {
Douglas Gregor2bec0412009-04-10 21:16:55 +0000930 std::string TargetTriple(BlobStart, BlobLen);
931 if (TargetTriple != Context.Target.getTargetTriple()) {
932 Diag(diag::warn_pch_target_triple)
933 << TargetTriple << Context.Target.getTargetTriple();
934 Diag(diag::note_ignoring_pch) << FileName;
935 return IgnorePCH;
936 }
937 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000938 }
Douglas Gregorafaf3082009-04-11 00:14:32 +0000939
940 case pch::IDENTIFIER_TABLE:
Douglas Gregor668c1a42009-04-21 22:25:48 +0000941 IdentifierTableData = BlobStart;
Douglas Gregor2b3a5a82009-04-25 19:10:14 +0000942 if (Record[0]) {
943 IdentifierLookupTable
944 = PCHIdentifierLookupTable::Create(
Douglas Gregor668c1a42009-04-21 22:25:48 +0000945 (const unsigned char *)IdentifierTableData + Record[0],
946 (const unsigned char *)IdentifierTableData,
947 PCHIdentifierLookupTrait(*this));
Douglas Gregor2b3a5a82009-04-25 19:10:14 +0000948 PP.getIdentifierTable().setExternalIdentifierLookup(this);
949 }
Douglas Gregorafaf3082009-04-11 00:14:32 +0000950 break;
951
952 case pch::IDENTIFIER_OFFSET:
Douglas Gregor2b3a5a82009-04-25 19:10:14 +0000953 if (!IdentifiersLoaded.empty()) {
Douglas Gregorafaf3082009-04-11 00:14:32 +0000954 Error("Duplicate IDENTIFIER_OFFSET record in PCH file");
955 return Failure;
956 }
Douglas Gregor2b3a5a82009-04-25 19:10:14 +0000957 IdentifierOffsets = (const uint32_t *)BlobStart;
958 IdentifiersLoaded.resize(Record[0]);
Douglas Gregor8c5a7602009-04-25 23:30:02 +0000959 PP.getHeaderSearchInfo().SetExternalLookup(this);
Douglas Gregorafaf3082009-04-11 00:14:32 +0000960 break;
Douglas Gregorfdd01722009-04-14 00:24:19 +0000961
962 case pch::EXTERNAL_DEFINITIONS:
963 if (!ExternalDefinitions.empty()) {
964 Error("Duplicate EXTERNAL_DEFINITIONS record in PCH file");
965 return Failure;
966 }
967 ExternalDefinitions.swap(Record);
968 break;
Douglas Gregor3e1af842009-04-17 22:13:46 +0000969
Douglas Gregorad1de002009-04-18 05:55:16 +0000970 case pch::SPECIAL_TYPES:
971 SpecialTypes.swap(Record);
972 break;
973
Douglas Gregor3e1af842009-04-17 22:13:46 +0000974 case pch::STATISTICS:
975 TotalNumStatements = Record[0];
Douglas Gregor37e26842009-04-21 23:56:24 +0000976 TotalNumMacros = Record[1];
Douglas Gregor25123082009-04-22 22:34:57 +0000977 TotalLexicalDeclContexts = Record[2];
978 TotalVisibleDeclContexts = Record[3];
Douglas Gregor3e1af842009-04-17 22:13:46 +0000979 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000980
Douglas Gregor4c0e86b2009-04-22 22:02:47 +0000981 case pch::TENTATIVE_DEFINITIONS:
982 if (!TentativeDefinitions.empty()) {
983 Error("Duplicate TENTATIVE_DEFINITIONS record in PCH file");
984 return Failure;
985 }
986 TentativeDefinitions.swap(Record);
987 break;
Douglas Gregor14c22f22009-04-22 22:18:58 +0000988
989 case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
990 if (!LocallyScopedExternalDecls.empty()) {
991 Error("Duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
992 return Failure;
993 }
994 LocallyScopedExternalDecls.swap(Record);
995 break;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000996
Douglas Gregor83941df2009-04-25 17:48:32 +0000997 case pch::SELECTOR_OFFSETS:
998 SelectorOffsets = (const uint32_t *)BlobStart;
999 TotalNumSelectors = Record[0];
1000 SelectorsLoaded.resize(TotalNumSelectors);
1001 break;
1002
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001003 case pch::METHOD_POOL:
Douglas Gregor83941df2009-04-25 17:48:32 +00001004 MethodPoolLookupTableData = (const unsigned char *)BlobStart;
1005 if (Record[0])
1006 MethodPoolLookupTable
1007 = PCHMethodPoolLookupTable::Create(
1008 MethodPoolLookupTableData + Record[0],
1009 MethodPoolLookupTableData,
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001010 PCHMethodPoolLookupTrait(*this));
Douglas Gregor83941df2009-04-25 17:48:32 +00001011 TotalSelectorsInMethodPool = Record[1];
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001012 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001013
1014 case pch::PP_COUNTER_VALUE:
1015 if (!Record.empty())
1016 PP.setCounterValue(Record[0]);
1017 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001018
1019 case pch::SOURCE_LOCATION_OFFSETS:
Chris Lattner090d9b52009-04-27 19:01:47 +00001020 SLocOffsets = (const uint32_t *)BlobStart;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001021 TotalNumSLocEntries = Record[0];
1022 PP.getSourceManager().PreallocateSLocEntries(this,
1023 TotalNumSLocEntries,
1024 Record[1]);
1025 break;
1026
1027 case pch::SOURCE_LOCATION_PRELOADS:
1028 for (unsigned I = 0, N = Record.size(); I != N; ++I) {
1029 PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
1030 if (Result != Success)
1031 return Result;
1032 }
1033 break;
Douglas Gregor4fed3f42009-04-27 18:38:38 +00001034
1035 case pch::STAT_CACHE:
1036 PP.getFileManager().setStatCache(
1037 new PCHStatCache((const unsigned char *)BlobStart + Record[0],
1038 (const unsigned char *)BlobStart,
1039 NumStatHits, NumStatMisses));
1040 break;
Douglas Gregorb81c1702009-04-27 20:06:05 +00001041
1042 case pch::EXT_VECTOR_DECLS:
1043 if (!ExtVectorDecls.empty()) {
1044 Error("Duplicate EXT_VECTOR_DECLS record in PCH file");
1045 return Failure;
1046 }
1047 ExtVectorDecls.swap(Record);
1048 break;
1049
1050 case pch::OBJC_CATEGORY_IMPLEMENTATIONS:
1051 if (!ObjCCategoryImpls.empty()) {
1052 Error("Duplicate OBJC_CATEGORY_IMPLEMENTATIONS record in PCH file");
1053 return Failure;
1054 }
1055 ObjCCategoryImpls.swap(Record);
1056 break;
Douglas Gregorafaf3082009-04-11 00:14:32 +00001057 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001058 }
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001059 Error("Premature end of bitstream");
1060 return Failure;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001061}
1062
Douglas Gregore1d918e2009-04-10 23:10:45 +00001063PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001064 // Set the PCH file name.
1065 this->FileName = FileName;
1066
Douglas Gregor2cf26342009-04-09 22:27:44 +00001067 // Open the PCH file.
1068 std::string ErrStr;
1069 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
Douglas Gregore1d918e2009-04-10 23:10:45 +00001070 if (!Buffer) {
1071 Error(ErrStr.c_str());
1072 return IgnorePCH;
1073 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001074
1075 // Initialize the stream
Chris Lattnerb9fa9172009-04-26 20:59:20 +00001076 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
1077 (const unsigned char *)Buffer->getBufferEnd());
1078 Stream.init(StreamFile);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001079
1080 // Sniff for the signature.
1081 if (Stream.Read(8) != 'C' ||
1082 Stream.Read(8) != 'P' ||
1083 Stream.Read(8) != 'C' ||
Douglas Gregore1d918e2009-04-10 23:10:45 +00001084 Stream.Read(8) != 'H') {
1085 Error("Not a PCH file");
1086 return IgnorePCH;
1087 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001088
Douglas Gregor2cf26342009-04-09 22:27:44 +00001089 while (!Stream.AtEndOfStream()) {
1090 unsigned Code = Stream.ReadCode();
1091
Douglas Gregore1d918e2009-04-10 23:10:45 +00001092 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
1093 Error("Invalid record at top-level");
1094 return Failure;
1095 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001096
1097 unsigned BlockID = Stream.ReadSubBlockID();
Douglas Gregor668c1a42009-04-21 22:25:48 +00001098
Douglas Gregor2cf26342009-04-09 22:27:44 +00001099 // We only know the PCH subblock ID.
1100 switch (BlockID) {
1101 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001102 if (Stream.ReadBlockInfoBlock()) {
1103 Error("Malformed BlockInfoBlock");
1104 return Failure;
1105 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001106 break;
1107 case pch::PCH_BLOCK_ID:
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001108 switch (ReadPCHBlock()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001109 case Success:
1110 break;
1111
1112 case Failure:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001113 return Failure;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001114
1115 case IgnorePCH:
Douglas Gregor2bec0412009-04-10 21:16:55 +00001116 // FIXME: We could consider reading through to the end of this
1117 // PCH block, skipping subblocks, to see if there are other
1118 // PCH blocks elsewhere.
Douglas Gregore1d918e2009-04-10 23:10:45 +00001119 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001120 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001121 break;
1122 default:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001123 if (Stream.SkipBlock()) {
1124 Error("Malformed block record");
1125 return Failure;
1126 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001127 break;
1128 }
1129 }
1130
1131 // Load the translation unit declaration
1132 ReadDeclRecord(DeclOffsets[0], 0);
1133
Douglas Gregor668c1a42009-04-21 22:25:48 +00001134 // Initialization of builtins and library builtins occurs before the
1135 // PCH file is read, so there may be some identifiers that were
1136 // loaded into the IdentifierTable before we intercepted the
1137 // creation of identifiers. Iterate through the list of known
1138 // identifiers and determine whether we have to establish
1139 // preprocessor definitions or top-level identifier declaration
1140 // chains for those identifiers.
1141 //
1142 // We copy the IdentifierInfo pointers to a small vector first,
1143 // since de-serializing declarations or macro definitions can add
1144 // new entries into the identifier table, invalidating the
1145 // iterators.
1146 llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
1147 for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
1148 IdEnd = PP.getIdentifierTable().end();
1149 Id != IdEnd; ++Id)
1150 Identifiers.push_back(Id->second);
1151 PCHIdentifierLookupTable *IdTable
1152 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1153 for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
1154 IdentifierInfo *II = Identifiers[I];
1155 // Look in the on-disk hash table for an entry for
1156 PCHIdentifierLookupTrait Info(*this, II);
1157 std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
1158 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
1159 if (Pos == IdTable->end())
1160 continue;
1161
1162 // Dereferencing the iterator has the effect of populating the
1163 // IdentifierInfo node with the various declarations it needs.
1164 (void)*Pos;
1165 }
1166
Douglas Gregorad1de002009-04-18 05:55:16 +00001167 // Load the special types.
1168 Context.setBuiltinVaListType(
1169 GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
Douglas Gregor319ac892009-04-23 22:29:11 +00001170 if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
1171 Context.setObjCIdType(GetType(Id));
1172 if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
1173 Context.setObjCSelType(GetType(Sel));
1174 if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
1175 Context.setObjCProtoType(GetType(Proto));
1176 if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
1177 Context.setObjCClassType(GetType(Class));
1178 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
1179 Context.setCFConstantStringType(GetType(String));
1180 if (unsigned FastEnum
1181 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
1182 Context.setObjCFastEnumerationStateType(GetType(FastEnum));
Douglas Gregor0b748912009-04-14 21:18:50 +00001183
Douglas Gregor668c1a42009-04-21 22:25:48 +00001184 return Success;
Douglas Gregor0b748912009-04-14 21:18:50 +00001185}
1186
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001187/// \brief Parse the record that corresponds to a LangOptions data
1188/// structure.
1189///
1190/// This routine compares the language options used to generate the
1191/// PCH file against the language options set for the current
1192/// compilation. For each option, we classify differences between the
1193/// two compiler states as either "benign" or "important". Benign
1194/// differences don't matter, and we accept them without complaint
1195/// (and without modifying the language options). Differences between
1196/// the states for important options cause the PCH file to be
1197/// unusable, so we emit a warning and return true to indicate that
1198/// there was an error.
1199///
1200/// \returns true if the PCH file is unacceptable, false otherwise.
1201bool PCHReader::ParseLanguageOptions(
1202 const llvm::SmallVectorImpl<uint64_t> &Record) {
1203 const LangOptions &LangOpts = Context.getLangOptions();
1204#define PARSE_LANGOPT_BENIGN(Option) ++Idx
1205#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
1206 if (Record[Idx] != LangOpts.Option) { \
1207 Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
1208 Diag(diag::note_ignoring_pch) << FileName; \
1209 return true; \
1210 } \
1211 ++Idx
1212
1213 unsigned Idx = 0;
1214 PARSE_LANGOPT_BENIGN(Trigraphs);
1215 PARSE_LANGOPT_BENIGN(BCPLComment);
1216 PARSE_LANGOPT_BENIGN(DollarIdents);
1217 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
1218 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
1219 PARSE_LANGOPT_BENIGN(ImplicitInt);
1220 PARSE_LANGOPT_BENIGN(Digraphs);
1221 PARSE_LANGOPT_BENIGN(HexFloats);
1222 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
1223 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
1224 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
1225 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
1226 PARSE_LANGOPT_IMPORTANT(NoExtensions, diag::warn_pch_extensions);
1227 PARSE_LANGOPT_BENIGN(CXXOperatorName);
1228 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
1229 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
1230 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
1231 PARSE_LANGOPT_BENIGN(PascalStrings);
1232 PARSE_LANGOPT_BENIGN(Boolean);
1233 PARSE_LANGOPT_BENIGN(WritableStrings);
1234 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
1235 diag::warn_pch_lax_vector_conversions);
1236 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
1237 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
1238 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
1239 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
1240 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
1241 diag::warn_pch_thread_safe_statics);
1242 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
1243 PARSE_LANGOPT_BENIGN(EmitAllDecls);
1244 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
1245 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
1246 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
1247 diag::warn_pch_heinous_extensions);
1248 // FIXME: Most of the options below are benign if the macro wasn't
1249 // used. Unfortunately, this means that a PCH compiled without
1250 // optimization can't be used with optimization turned on, even
1251 // though the only thing that changes is whether __OPTIMIZE__ was
1252 // defined... but if __OPTIMIZE__ never showed up in the header, it
1253 // doesn't matter. We could consider making this some special kind
1254 // of check.
1255 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
1256 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
1257 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
1258 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
1259 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
1260 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
1261 if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
1262 Diag(diag::warn_pch_gc_mode)
1263 << (unsigned)Record[Idx] << LangOpts.getGCMode();
1264 Diag(diag::note_ignoring_pch) << FileName;
1265 return true;
1266 }
1267 ++Idx;
1268 PARSE_LANGOPT_BENIGN(getVisibilityMode());
1269 PARSE_LANGOPT_BENIGN(InstantiationDepth);
1270#undef PARSE_LANGOPT_IRRELEVANT
1271#undef PARSE_LANGOPT_BENIGN
1272
1273 return false;
1274}
1275
Douglas Gregor2cf26342009-04-09 22:27:44 +00001276/// \brief Read and return the type at the given offset.
1277///
1278/// This routine actually reads the record corresponding to the type
1279/// at the given offset in the bitstream. It is a helper routine for
1280/// GetType, which deals with reading type IDs.
1281QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregor0b748912009-04-14 21:18:50 +00001282 // Keep track of where we are in the stream, then jump back there
1283 // after reading this type.
1284 SavedStreamPosition SavedPosition(Stream);
1285
Douglas Gregor2cf26342009-04-09 22:27:44 +00001286 Stream.JumpToBit(Offset);
1287 RecordData Record;
1288 unsigned Code = Stream.ReadCode();
1289 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
Douglas Gregor6d473962009-04-15 22:00:08 +00001290 case pch::TYPE_EXT_QUAL: {
1291 assert(Record.size() == 3 &&
1292 "Incorrect encoding of extended qualifier type");
1293 QualType Base = GetType(Record[0]);
1294 QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1];
1295 unsigned AddressSpace = Record[2];
1296
1297 QualType T = Base;
1298 if (GCAttr != QualType::GCNone)
1299 T = Context.getObjCGCQualType(T, GCAttr);
1300 if (AddressSpace)
1301 T = Context.getAddrSpaceQualType(T, AddressSpace);
1302 return T;
1303 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001304
Douglas Gregor2cf26342009-04-09 22:27:44 +00001305 case pch::TYPE_FIXED_WIDTH_INT: {
1306 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
1307 return Context.getFixedWidthIntType(Record[0], Record[1]);
1308 }
1309
1310 case pch::TYPE_COMPLEX: {
1311 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1312 QualType ElemType = GetType(Record[0]);
1313 return Context.getComplexType(ElemType);
1314 }
1315
1316 case pch::TYPE_POINTER: {
1317 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1318 QualType PointeeType = GetType(Record[0]);
1319 return Context.getPointerType(PointeeType);
1320 }
1321
1322 case pch::TYPE_BLOCK_POINTER: {
1323 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1324 QualType PointeeType = GetType(Record[0]);
1325 return Context.getBlockPointerType(PointeeType);
1326 }
1327
1328 case pch::TYPE_LVALUE_REFERENCE: {
1329 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1330 QualType PointeeType = GetType(Record[0]);
1331 return Context.getLValueReferenceType(PointeeType);
1332 }
1333
1334 case pch::TYPE_RVALUE_REFERENCE: {
1335 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1336 QualType PointeeType = GetType(Record[0]);
1337 return Context.getRValueReferenceType(PointeeType);
1338 }
1339
1340 case pch::TYPE_MEMBER_POINTER: {
1341 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1342 QualType PointeeType = GetType(Record[0]);
1343 QualType ClassType = GetType(Record[1]);
1344 return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
1345 }
1346
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001347 case pch::TYPE_CONSTANT_ARRAY: {
1348 QualType ElementType = GetType(Record[0]);
1349 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1350 unsigned IndexTypeQuals = Record[2];
1351 unsigned Idx = 3;
1352 llvm::APInt Size = ReadAPInt(Record, Idx);
1353 return Context.getConstantArrayType(ElementType, Size, ASM, IndexTypeQuals);
1354 }
1355
1356 case pch::TYPE_INCOMPLETE_ARRAY: {
1357 QualType ElementType = GetType(Record[0]);
1358 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1359 unsigned IndexTypeQuals = Record[2];
1360 return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
1361 }
1362
1363 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregor0b748912009-04-14 21:18:50 +00001364 QualType ElementType = GetType(Record[0]);
1365 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1366 unsigned IndexTypeQuals = Record[2];
Chris Lattnerda930612009-04-27 05:58:23 +00001367 return Context.getVariableArrayType(ElementType, ReadTypeExpr(),
Douglas Gregor0b748912009-04-14 21:18:50 +00001368 ASM, IndexTypeQuals);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001369 }
1370
1371 case pch::TYPE_VECTOR: {
1372 if (Record.size() != 2) {
1373 Error("Incorrect encoding of vector type in PCH file");
1374 return QualType();
1375 }
1376
1377 QualType ElementType = GetType(Record[0]);
1378 unsigned NumElements = Record[1];
1379 return Context.getVectorType(ElementType, NumElements);
1380 }
1381
1382 case pch::TYPE_EXT_VECTOR: {
1383 if (Record.size() != 2) {
1384 Error("Incorrect encoding of extended vector type in PCH file");
1385 return QualType();
1386 }
1387
1388 QualType ElementType = GetType(Record[0]);
1389 unsigned NumElements = Record[1];
1390 return Context.getExtVectorType(ElementType, NumElements);
1391 }
1392
1393 case pch::TYPE_FUNCTION_NO_PROTO: {
1394 if (Record.size() != 1) {
1395 Error("Incorrect encoding of no-proto function type");
1396 return QualType();
1397 }
1398 QualType ResultType = GetType(Record[0]);
1399 return Context.getFunctionNoProtoType(ResultType);
1400 }
1401
1402 case pch::TYPE_FUNCTION_PROTO: {
1403 QualType ResultType = GetType(Record[0]);
1404 unsigned Idx = 1;
1405 unsigned NumParams = Record[Idx++];
1406 llvm::SmallVector<QualType, 16> ParamTypes;
1407 for (unsigned I = 0; I != NumParams; ++I)
1408 ParamTypes.push_back(GetType(Record[Idx++]));
1409 bool isVariadic = Record[Idx++];
1410 unsigned Quals = Record[Idx++];
1411 return Context.getFunctionType(ResultType, &ParamTypes[0], NumParams,
1412 isVariadic, Quals);
1413 }
1414
1415 case pch::TYPE_TYPEDEF:
1416 assert(Record.size() == 1 && "Incorrect encoding of typedef type");
1417 return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
1418
1419 case pch::TYPE_TYPEOF_EXPR:
Chris Lattnerda930612009-04-27 05:58:23 +00001420 return Context.getTypeOfExprType(ReadTypeExpr());
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001421
1422 case pch::TYPE_TYPEOF: {
1423 if (Record.size() != 1) {
1424 Error("Incorrect encoding of typeof(type) in PCH file");
1425 return QualType();
1426 }
1427 QualType UnderlyingType = GetType(Record[0]);
1428 return Context.getTypeOfType(UnderlyingType);
1429 }
1430
1431 case pch::TYPE_RECORD:
Douglas Gregor8c700062009-04-13 21:20:57 +00001432 assert(Record.size() == 1 && "Incorrect encoding of record type");
1433 return Context.getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001434
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001435 case pch::TYPE_ENUM:
1436 assert(Record.size() == 1 && "Incorrect encoding of enum type");
1437 return Context.getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
1438
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001439 case pch::TYPE_OBJC_INTERFACE:
Chris Lattner4dcf151a2009-04-22 05:57:30 +00001440 assert(Record.size() == 1 && "Incorrect encoding of objc interface type");
1441 return Context.getObjCInterfaceType(
1442 cast<ObjCInterfaceDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001443
Chris Lattnerc6fa4452009-04-22 06:45:28 +00001444 case pch::TYPE_OBJC_QUALIFIED_INTERFACE: {
1445 unsigned Idx = 0;
1446 ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
1447 unsigned NumProtos = Record[Idx++];
1448 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1449 for (unsigned I = 0; I != NumProtos; ++I)
1450 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
1451 return Context.getObjCQualifiedInterfaceType(ItfD, &Protos[0], NumProtos);
1452 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001453
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001454 case pch::TYPE_OBJC_QUALIFIED_ID: {
1455 unsigned Idx = 0;
1456 unsigned NumProtos = Record[Idx++];
1457 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1458 for (unsigned I = 0; I != NumProtos; ++I)
1459 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
1460 return Context.getObjCQualifiedIdType(&Protos[0], NumProtos);
1461 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001462 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001463 // Suppress a GCC warning
1464 return QualType();
1465}
1466
Douglas Gregor2cf26342009-04-09 22:27:44 +00001467
Douglas Gregor8038d512009-04-10 17:25:41 +00001468QualType PCHReader::GetType(pch::TypeID ID) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001469 unsigned Quals = ID & 0x07;
1470 unsigned Index = ID >> 3;
1471
1472 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
1473 QualType T;
1474 switch ((pch::PredefinedTypeIDs)Index) {
1475 case pch::PREDEF_TYPE_NULL_ID: return QualType();
1476 case pch::PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
1477 case pch::PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
1478
1479 case pch::PREDEF_TYPE_CHAR_U_ID:
1480 case pch::PREDEF_TYPE_CHAR_S_ID:
1481 // FIXME: Check that the signedness of CharTy is correct!
1482 T = Context.CharTy;
1483 break;
1484
1485 case pch::PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
1486 case pch::PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
1487 case pch::PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
1488 case pch::PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
1489 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
1490 case pch::PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
1491 case pch::PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
1492 case pch::PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
1493 case pch::PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
1494 case pch::PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
1495 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
1496 case pch::PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
1497 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
1498 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
1499 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
1500 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
1501 }
1502
1503 assert(!T.isNull() && "Unknown predefined type");
1504 return T.getQualifiedType(Quals);
1505 }
1506
1507 Index -= pch::NUM_PREDEF_TYPE_IDS;
Douglas Gregor366809a2009-04-26 03:49:13 +00001508 assert(Index < TypesLoaded.size() && "Type index out-of-range");
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001509 if (!TypesLoaded[Index])
1510 TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr();
Douglas Gregor2cf26342009-04-09 22:27:44 +00001511
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001512 return QualType(TypesLoaded[Index], Quals);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001513}
1514
Douglas Gregor8038d512009-04-10 17:25:41 +00001515Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001516 if (ID == 0)
1517 return 0;
1518
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001519 if (ID > DeclsLoaded.size()) {
1520 Error("Declaration ID out-of-range for PCH file");
1521 return 0;
1522 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001523
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001524 unsigned Index = ID - 1;
1525 if (!DeclsLoaded[Index])
1526 ReadDeclRecord(DeclOffsets[Index], Index);
1527
1528 return DeclsLoaded[Index];
Douglas Gregor2cf26342009-04-09 22:27:44 +00001529}
1530
Chris Lattner887e2b32009-04-27 05:46:25 +00001531/// \brief Resolve the offset of a statement into a statement.
1532///
1533/// This operation will read a new statement from the external
1534/// source each time it is called, and is meant to be used via a
1535/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
1536Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
Chris Lattnerda930612009-04-27 05:58:23 +00001537 // Since we know tha this statement is part of a decl, make sure to use the
1538 // decl cursor to read it.
1539 DeclsCursor.JumpToBit(Offset);
1540 return ReadStmt(DeclsCursor);
Douglas Gregor250fc9c2009-04-18 00:07:54 +00001541}
1542
Douglas Gregor2cf26342009-04-09 22:27:44 +00001543bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregor8038d512009-04-10 17:25:41 +00001544 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001545 assert(DC->hasExternalLexicalStorage() &&
1546 "DeclContext has no lexical decls in storage");
1547 uint64_t Offset = DeclContextOffsets[DC].first;
1548 assert(Offset && "DeclContext has no lexical decls in storage");
1549
Douglas Gregor0b748912009-04-14 21:18:50 +00001550 // Keep track of where we are in the stream, then jump back there
1551 // after reading this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001552 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00001553
Douglas Gregor2cf26342009-04-09 22:27:44 +00001554 // Load the record containing all of the declarations lexically in
1555 // this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001556 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001557 RecordData Record;
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001558 unsigned Code = DeclsCursor.ReadCode();
1559 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00001560 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001561 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
1562
1563 // Load all of the declaration IDs
1564 Decls.clear();
1565 Decls.insert(Decls.end(), Record.begin(), Record.end());
Douglas Gregor25123082009-04-22 22:34:57 +00001566 ++NumLexicalDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001567 return false;
1568}
1569
1570bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001571 llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001572 assert(DC->hasExternalVisibleStorage() &&
1573 "DeclContext has no visible decls in storage");
1574 uint64_t Offset = DeclContextOffsets[DC].second;
1575 assert(Offset && "DeclContext has no visible decls in storage");
1576
Douglas Gregor0b748912009-04-14 21:18:50 +00001577 // Keep track of where we are in the stream, then jump back there
1578 // after reading this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001579 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00001580
Douglas Gregor2cf26342009-04-09 22:27:44 +00001581 // Load the record containing all of the declarations visible in
1582 // this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001583 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001584 RecordData Record;
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001585 unsigned Code = DeclsCursor.ReadCode();
1586 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00001587 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001588 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
1589 if (Record.size() == 0)
1590 return false;
1591
1592 Decls.clear();
1593
1594 unsigned Idx = 0;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001595 while (Idx < Record.size()) {
1596 Decls.push_back(VisibleDeclaration());
1597 Decls.back().Name = ReadDeclarationName(Record, Idx);
1598
Douglas Gregor2cf26342009-04-09 22:27:44 +00001599 unsigned Size = Record[Idx++];
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001600 llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001601 LoadedDecls.reserve(Size);
1602 for (unsigned I = 0; I < Size; ++I)
1603 LoadedDecls.push_back(Record[Idx++]);
1604 }
1605
Douglas Gregor25123082009-04-22 22:34:57 +00001606 ++NumVisibleDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001607 return false;
1608}
1609
Douglas Gregorfdd01722009-04-14 00:24:19 +00001610void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
Douglas Gregor0af2ca42009-04-22 19:09:20 +00001611 this->Consumer = Consumer;
1612
Douglas Gregorfdd01722009-04-14 00:24:19 +00001613 if (!Consumer)
1614 return;
1615
1616 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
1617 Decl *D = GetDecl(ExternalDefinitions[I]);
1618 DeclGroupRef DG(D);
1619 Consumer->HandleTopLevelDecl(DG);
1620 }
Douglas Gregorc62a2fe2009-04-25 00:41:30 +00001621
1622 for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
1623 DeclGroupRef DG(InterestingDecls[I]);
1624 Consumer->HandleTopLevelDecl(DG);
1625 }
Douglas Gregorfdd01722009-04-14 00:24:19 +00001626}
1627
Douglas Gregor2cf26342009-04-09 22:27:44 +00001628void PCHReader::PrintStats() {
1629 std::fprintf(stderr, "*** PCH Statistics:\n");
1630
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001631 unsigned NumTypesLoaded
1632 = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
1633 (Type *)0);
1634 unsigned NumDeclsLoaded
1635 = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
1636 (Decl *)0);
1637 unsigned NumIdentifiersLoaded
1638 = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
1639 IdentifiersLoaded.end(),
1640 (IdentifierInfo *)0);
1641 unsigned NumSelectorsLoaded
1642 = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
1643 SelectorsLoaded.end(),
1644 Selector());
Douglas Gregor2d41cc12009-04-13 20:50:16 +00001645
Douglas Gregor4fed3f42009-04-27 18:38:38 +00001646 std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
1647 std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001648 if (TotalNumSLocEntries)
1649 std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
1650 NumSLocEntriesRead, TotalNumSLocEntries,
1651 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001652 if (!TypesLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00001653 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001654 NumTypesLoaded, (unsigned)TypesLoaded.size(),
1655 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
1656 if (!DeclsLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00001657 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001658 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
1659 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001660 if (!IdentifiersLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00001661 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001662 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
1663 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
Douglas Gregor83941df2009-04-25 17:48:32 +00001664 if (TotalNumSelectors)
1665 std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
1666 NumSelectorsLoaded, TotalNumSelectors,
1667 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
1668 if (TotalNumStatements)
1669 std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
1670 NumStatementsRead, TotalNumStatements,
1671 ((float)NumStatementsRead/TotalNumStatements * 100));
1672 if (TotalNumMacros)
1673 std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
1674 NumMacrosRead, TotalNumMacros,
1675 ((float)NumMacrosRead/TotalNumMacros * 100));
1676 if (TotalLexicalDeclContexts)
1677 std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
1678 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
1679 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
1680 * 100));
1681 if (TotalVisibleDeclContexts)
1682 std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
1683 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
1684 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
1685 * 100));
1686 if (TotalSelectorsInMethodPool) {
1687 std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
1688 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
1689 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
1690 * 100));
1691 std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
1692 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001693 std::fprintf(stderr, "\n");
1694}
1695
Douglas Gregor668c1a42009-04-21 22:25:48 +00001696void PCHReader::InitializeSema(Sema &S) {
1697 SemaObj = &S;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001698 S.ExternalSource = this;
1699
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00001700 // Makes sure any declarations that were deserialized "too early"
1701 // still get added to the identifier's declaration chains.
1702 for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
1703 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
1704 SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
Douglas Gregor668c1a42009-04-21 22:25:48 +00001705 }
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00001706 PreloadedDecls.clear();
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00001707
1708 // If there were any tentative definitions, deserialize them and add
1709 // them to Sema's table of tentative definitions.
1710 for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
1711 VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
1712 SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
1713 }
Douglas Gregor14c22f22009-04-22 22:18:58 +00001714
1715 // If there were any locally-scoped external declarations,
1716 // deserialize them and add them to Sema's table of locally-scoped
1717 // external declarations.
1718 for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
1719 NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
1720 SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
1721 }
Douglas Gregorb81c1702009-04-27 20:06:05 +00001722
1723 // If there were any ext_vector type declarations, deserialize them
1724 // and add them to Sema's vector of such declarations.
1725 for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
1726 SemaObj->ExtVectorDecls.push_back(
1727 cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
1728
1729 // If there were any Objective-C category implementations,
1730 // deserialize them and add them to Sema's vector of such
1731 // definitions.
1732 for (unsigned I = 0, N = ObjCCategoryImpls.size(); I != N; ++I)
1733 SemaObj->ObjCCategoryImpls.push_back(
1734 cast<ObjCCategoryImplDecl>(GetDecl(ObjCCategoryImpls[I])));
Douglas Gregor668c1a42009-04-21 22:25:48 +00001735}
1736
1737IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
1738 // Try to find this name within our on-disk hash table
1739 PCHIdentifierLookupTable *IdTable
1740 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1741 std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
1742 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
1743 if (Pos == IdTable->end())
1744 return 0;
1745
1746 // Dereferencing the iterator has the effect of building the
1747 // IdentifierInfo node and populating it with the various
1748 // declarations it needs.
1749 return *Pos;
1750}
1751
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001752std::pair<ObjCMethodList, ObjCMethodList>
1753PCHReader::ReadMethodPool(Selector Sel) {
1754 if (!MethodPoolLookupTable)
1755 return std::pair<ObjCMethodList, ObjCMethodList>();
1756
1757 // Try to find this selector within our on-disk hash table.
1758 PCHMethodPoolLookupTable *PoolTable
1759 = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
1760 PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
Douglas Gregor83941df2009-04-25 17:48:32 +00001761 if (Pos == PoolTable->end()) {
1762 ++NumMethodPoolMisses;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001763 return std::pair<ObjCMethodList, ObjCMethodList>();;
Douglas Gregor83941df2009-04-25 17:48:32 +00001764 }
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001765
Douglas Gregor83941df2009-04-25 17:48:32 +00001766 ++NumMethodPoolSelectorsRead;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001767 return *Pos;
1768}
1769
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001770void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
Douglas Gregor668c1a42009-04-21 22:25:48 +00001771 assert(ID && "Non-zero identifier ID required");
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001772 assert(ID <= IdentifiersLoaded.size() && "Identifier ID out of range");
1773 IdentifiersLoaded[ID - 1] = II;
Douglas Gregor668c1a42009-04-21 22:25:48 +00001774}
1775
Chris Lattner7356a312009-04-11 21:15:38 +00001776IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregorafaf3082009-04-11 00:14:32 +00001777 if (ID == 0)
1778 return 0;
Chris Lattner7356a312009-04-11 21:15:38 +00001779
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001780 if (!IdentifierTableData || IdentifiersLoaded.empty()) {
Douglas Gregorafaf3082009-04-11 00:14:32 +00001781 Error("No identifier table in PCH file");
1782 return 0;
1783 }
Chris Lattner7356a312009-04-11 21:15:38 +00001784
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001785 if (!IdentifiersLoaded[ID - 1]) {
1786 uint32_t Offset = IdentifierOffsets[ID - 1];
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001787 const char *Str = IdentifierTableData + Offset;
Douglas Gregord6595a42009-04-25 21:04:17 +00001788
1789 // If there is an identifier lookup table, but the offset of this
1790 // string is after the identifier table itself, then we know that
1791 // this string is not in the on-disk hash table. Therefore,
1792 // disable lookup into the hash table when looking for this
1793 // identifier.
1794 PCHIdentifierLookupTable *IdTable
1795 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001796 if (!IdTable ||
1797 Offset >= uint32_t(IdTable->getBuckets() - IdTable->getBase())) {
1798 // Turn off lookup into the on-disk hash table. We know that
1799 // this identifier is not there.
1800 if (IdTable)
1801 PP.getIdentifierTable().setExternalIdentifierLookup(0);
Douglas Gregord6595a42009-04-25 21:04:17 +00001802
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001803 // All of the strings in the PCH file are preceded by a 16-bit
1804 // length. Extract that 16-bit length to avoid having to execute
1805 // strlen().
1806 const char *StrLenPtr = Str - 2;
1807 unsigned StrLen = (((unsigned) StrLenPtr[0])
1808 | (((unsigned) StrLenPtr[1]) << 8)) - 1;
1809 IdentifiersLoaded[ID - 1] = &Context.Idents.get(Str, Str + StrLen);
Douglas Gregord6595a42009-04-25 21:04:17 +00001810
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001811 // Turn on lookup into the on-disk hash table, if we have an
1812 // on-disk hash table.
1813 if (IdTable)
1814 PP.getIdentifierTable().setExternalIdentifierLookup(this);
1815 } else {
1816 // The identifier is a key in our on-disk hash table. Since we
1817 // know where the hash table entry starts, just read in this
1818 // (key, value) pair.
1819 PCHIdentifierLookupTrait Trait(const_cast<PCHReader &>(*this));
1820 const unsigned char *Pos = (const unsigned char *)Str - 4;
1821 std::pair<unsigned, unsigned> KeyDataLengths
1822 = Trait.ReadKeyDataLength(Pos);
Douglas Gregord6595a42009-04-25 21:04:17 +00001823
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001824 PCHIdentifierLookupTrait::internal_key_type InternalKey
1825 = Trait.ReadKey(Pos, KeyDataLengths.first);
1826 Pos = (const unsigned char *)Str + KeyDataLengths.first;
1827 IdentifiersLoaded[ID - 1] = Trait.ReadData(InternalKey, Pos,
1828 KeyDataLengths.second);
1829 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001830 }
Chris Lattner7356a312009-04-11 21:15:38 +00001831
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001832 return IdentifiersLoaded[ID - 1];
Douglas Gregor2cf26342009-04-09 22:27:44 +00001833}
1834
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001835void PCHReader::ReadSLocEntry(unsigned ID) {
1836 ReadSLocEntryRecord(ID);
1837}
1838
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001839Selector PCHReader::DecodeSelector(unsigned ID) {
1840 if (ID == 0)
1841 return Selector();
1842
Douglas Gregor83941df2009-04-25 17:48:32 +00001843 if (!MethodPoolLookupTableData) {
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001844 Error("No selector table in PCH file");
1845 return Selector();
1846 }
Douglas Gregor83941df2009-04-25 17:48:32 +00001847
1848 if (ID > TotalNumSelectors) {
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001849 Error("Selector ID out of range");
1850 return Selector();
1851 }
Douglas Gregor83941df2009-04-25 17:48:32 +00001852
1853 unsigned Index = ID - 1;
1854 if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
1855 // Load this selector from the selector table.
1856 // FIXME: endianness portability issues with SelectorOffsets table
1857 PCHMethodPoolLookupTrait Trait(*this);
1858 SelectorsLoaded[Index]
1859 = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
1860 }
1861
1862 return SelectorsLoaded[Index];
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001863}
1864
Douglas Gregor2cf26342009-04-09 22:27:44 +00001865DeclarationName
1866PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
1867 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
1868 switch (Kind) {
1869 case DeclarationName::Identifier:
1870 return DeclarationName(GetIdentifierInfo(Record, Idx));
1871
1872 case DeclarationName::ObjCZeroArgSelector:
1873 case DeclarationName::ObjCOneArgSelector:
1874 case DeclarationName::ObjCMultiArgSelector:
Steve Naroffa7503a72009-04-23 15:15:40 +00001875 return DeclarationName(GetSelector(Record, Idx));
Douglas Gregor2cf26342009-04-09 22:27:44 +00001876
1877 case DeclarationName::CXXConstructorName:
1878 return Context.DeclarationNames.getCXXConstructorName(
1879 GetType(Record[Idx++]));
1880
1881 case DeclarationName::CXXDestructorName:
1882 return Context.DeclarationNames.getCXXDestructorName(
1883 GetType(Record[Idx++]));
1884
1885 case DeclarationName::CXXConversionFunctionName:
1886 return Context.DeclarationNames.getCXXConversionFunctionName(
1887 GetType(Record[Idx++]));
1888
1889 case DeclarationName::CXXOperatorName:
1890 return Context.DeclarationNames.getCXXOperatorName(
1891 (OverloadedOperatorKind)Record[Idx++]);
1892
1893 case DeclarationName::CXXUsingDirective:
1894 return DeclarationName::getUsingDirectiveName();
1895 }
1896
1897 // Required to silence GCC warning
1898 return DeclarationName();
1899}
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001900
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001901/// \brief Read an integral value
1902llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
1903 unsigned BitWidth = Record[Idx++];
1904 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
1905 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
1906 Idx += NumWords;
1907 return Result;
1908}
1909
1910/// \brief Read a signed integral value
1911llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
1912 bool isUnsigned = Record[Idx++];
1913 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
1914}
1915
Douglas Gregor17fc2232009-04-14 21:55:33 +00001916/// \brief Read a floating-point value
1917llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
Douglas Gregor17fc2232009-04-14 21:55:33 +00001918 return llvm::APFloat(ReadAPInt(Record, Idx));
1919}
1920
Douglas Gregor68a2eb02009-04-15 21:30:51 +00001921// \brief Read a string
1922std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
1923 unsigned Len = Record[Idx++];
1924 std::string Result(&Record[Idx], &Record[Idx] + Len);
1925 Idx += Len;
1926 return Result;
1927}
1928
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001929DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregore1d918e2009-04-10 23:10:45 +00001930 return Diag(SourceLocation(), DiagID);
1931}
1932
1933DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
1934 return PP.getDiagnostics().Report(FullSourceLoc(Loc,
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001935 Context.getSourceManager()),
1936 DiagID);
1937}
Douglas Gregor025452f2009-04-17 00:04:06 +00001938
Douglas Gregor668c1a42009-04-21 22:25:48 +00001939/// \brief Retrieve the identifier table associated with the
1940/// preprocessor.
1941IdentifierTable &PCHReader::getIdentifierTable() {
1942 return PP.getIdentifierTable();
1943}
1944
Douglas Gregor025452f2009-04-17 00:04:06 +00001945/// \brief Record that the given ID maps to the given switch-case
1946/// statement.
1947void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
1948 assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
1949 SwitchCaseStmts[ID] = SC;
1950}
1951
1952/// \brief Retrieve the switch-case statement with the given ID.
1953SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
1954 assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
1955 return SwitchCaseStmts[ID];
1956}
Douglas Gregor1de05fe2009-04-17 18:18:49 +00001957
1958/// \brief Record that the given label statement has been
1959/// deserialized and has the given ID.
1960void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
1961 assert(LabelStmts.find(ID) == LabelStmts.end() &&
1962 "Deserialized label twice");
1963 LabelStmts[ID] = S;
1964
1965 // If we've already seen any goto statements that point to this
1966 // label, resolve them now.
1967 typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
1968 std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
1969 for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
1970 Goto->second->setLabel(S);
1971 UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00001972
1973 // If we've already seen any address-label statements that point to
1974 // this label, resolve them now.
1975 typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
1976 std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
1977 = UnresolvedAddrLabelExprs.equal_range(ID);
1978 for (AddrLabelIter AddrLabel = AddrLabels.first;
1979 AddrLabel != AddrLabels.second; ++AddrLabel)
1980 AddrLabel->second->setLabel(S);
1981 UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
Douglas Gregor1de05fe2009-04-17 18:18:49 +00001982}
1983
1984/// \brief Set the label of the given statement to the label
1985/// identified by ID.
1986///
1987/// Depending on the order in which the label and other statements
1988/// referencing that label occur, this operation may complete
1989/// immediately (updating the statement) or it may queue the
1990/// statement to be back-patched later.
1991void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
1992 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
1993 if (Label != LabelStmts.end()) {
1994 // We've already seen this label, so set the label of the goto and
1995 // we're done.
1996 S->setLabel(Label->second);
1997 } else {
1998 // We haven't seen this label yet, so add this goto to the set of
1999 // unresolved goto statements.
2000 UnresolvedGotoStmts.insert(std::make_pair(ID, S));
2001 }
2002}
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002003
2004/// \brief Set the label of the given expression to the label
2005/// identified by ID.
2006///
2007/// Depending on the order in which the label and other statements
2008/// referencing that label occur, this operation may complete
2009/// immediately (updating the statement) or it may queue the
2010/// statement to be back-patched later.
2011void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
2012 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2013 if (Label != LabelStmts.end()) {
2014 // We've already seen this label, so set the label of the
2015 // label-address expression and we're done.
2016 S->setLabel(Label->second);
2017 } else {
2018 // We haven't seen this label yet, so add this label-address
2019 // expression to the set of unresolved label-address expressions.
2020 UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
2021 }
2022}