blob: c1cb87bc160d78866db01f5a5db55d84d1e8f3ff [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//===----------------------------------------------------------------------===//
Chris Lattner09547942009-04-27 05:14:47 +000013
Douglas Gregorc34897d2009-04-09 22:27:44 +000014#include "clang/Frontend/PCHReader.h"
Douglas Gregor179cfb12009-04-10 20:39:37 +000015#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregorc713da92009-04-21 22:25:48 +000016#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
Douglas Gregor631f6c62009-04-14 00:24:19 +000017#include "clang/AST/ASTConsumer.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000018#include "clang/AST/ASTContext.h"
Douglas Gregorc10f86f2009-04-14 21:18:50 +000019#include "clang/AST/Expr.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000020#include "clang/AST/Type.h"
Chris Lattnerdb1c81b2009-04-10 21:41:48 +000021#include "clang/Lex/MacroInfo.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000022#include "clang/Lex/Preprocessor.h"
Steve Naroffcda68f22009-04-24 20:03:17 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregorc713da92009-04-21 22:25:48 +000024#include "clang/Basic/OnDiskHashTable.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000025#include "clang/Basic/SourceManager.h"
Douglas Gregor635f97f2009-04-13 16:31:14 +000026#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000027#include "clang/Basic/FileManager.h"
Douglas Gregorb5887f32009-04-10 21:16:55 +000028#include "clang/Basic/TargetInfo.h"
Douglas Gregorc34897d2009-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 Gregor6cc5d192009-04-27 18:38:38 +000034#include <sys/stat.h>
Douglas Gregorc34897d2009-04-09 22:27:44 +000035using namespace clang;
36
37//===----------------------------------------------------------------------===//
Douglas Gregorc713da92009-04-21 22:25:48 +000038// PCH reader implementation
39//===----------------------------------------------------------------------===//
40
Chris Lattner270d29a2009-04-27 21:45:14 +000041PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context)
Chris Lattner09547942009-04-27 05:14:47 +000042 : 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 Gregor6cc5d192009-04-27 18:38:38 +000047 TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
48 NumSLocEntriesRead(0), NumStatementsRead(0),
Douglas Gregor32e231c2009-04-27 06:38:32 +000049 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Chris Lattner09547942009-04-27 05:14:47 +000050 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
51
52PCHReader::~PCHReader() {}
53
Chris Lattner3ef21962009-04-27 05:58:23 +000054Expr *PCHReader::ReadDeclExpr() {
55 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
56}
57
58Expr *PCHReader::ReadTypeExpr() {
Chris Lattner3282c392009-04-27 05:41:06 +000059 return dyn_cast_or_null<Expr>(ReadStmt(Stream));
Chris Lattner09547942009-04-27 05:14:47 +000060}
61
62
Douglas Gregorc713da92009-04-21 22:25:48 +000063namespace {
Douglas Gregorc3221aa2009-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 Gregor2d711832009-04-25 17:48:32 +0000103 internal_key_type ReadKey(const unsigned char* d, unsigned) {
Douglas Gregorc3221aa2009-04-24 21:10:55 +0000104 using namespace clang::io;
Chris Lattner270d29a2009-04-27 21:45:14 +0000105 SelectorTable &SelTable = Reader.getContext()->Selectors;
Douglas Gregorc3221aa2009-04-24 21:10:55 +0000106 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 Gregorc713da92009-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 Gregor4bb24882009-04-25 20:26:24 +0000207 unsigned DataLen = ReadUnalignedLE16(d);
Douglas Gregor85c4a872009-04-25 21:04:17 +0000208 unsigned KeyLen = ReadUnalignedLE16(d);
Douglas Gregorc713da92009-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 Gregor2554cf22009-04-22 21:15:06 +0000222 uint32_t Bits = ReadUnalignedLE32(d);
Douglas Gregorda38c6c2009-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 Gregorc713da92009-04-21 22:25:48 +0000236 pch::IdentID ID = ReadUnalignedLE32(d);
Douglas Gregorda38c6c2009-04-22 18:49:13 +0000237 assert(Bits == 0 && "Extra bits in the identifier?");
Douglas Gregorc713da92009-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 Gregor4bb24882009-04-25 20:26:24 +0000244 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
245 k.first, k.first + k.second);
Douglas Gregorc713da92009-04-21 22:25:48 +0000246 Reader.SetIdentifierInfo(ID, II);
247
Douglas Gregorda38c6c2009-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 Gregore0ad2dd2009-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 Gregorc713da92009-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();
Chris Lattnerea436b82009-04-27 22:17:41 +0000273 if (Reader.getContext() == 0) return II;
Chris Lattner772a7c12009-04-27 22:02:30 +0000274
Douglas Gregorc713da92009-04-21 22:25:48 +0000275 while (DataLen > 0) {
276 NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
Douglas Gregorc713da92009-04-21 22:25:48 +0000277 if (SemaObj) {
278 // Introduce this declaration into the translation-unit scope
279 // and add it to the declaration chain for this identifier, so
280 // that (unqualified) name lookup will find it.
281 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
282 SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
283 } else {
284 // Queue this declaration so that it will be added to the
285 // translation unit scope and identifier's declaration chain
286 // once a Sema object is known.
Douglas Gregor2554cf22009-04-22 21:15:06 +0000287 Reader.PreloadedDecls.push_back(D);
Douglas Gregorc713da92009-04-21 22:25:48 +0000288 }
289
290 DataLen -= 4;
291 }
292 return II;
293 }
294};
295
296} // end anonymous namespace
297
298/// \brief The on-disk hash table used to contain information about
299/// all of the identifiers in the program.
300typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
301 PCHIdentifierLookupTable;
302
Douglas Gregorc34897d2009-04-09 22:27:44 +0000303// FIXME: use the diagnostics machinery
304static bool Error(const char *Str) {
305 std::fprintf(stderr, "%s\n", Str);
306 return true;
307}
308
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000309/// \brief Check the contents of the predefines buffer against the
310/// contents of the predefines buffer used to build the PCH file.
311///
312/// The contents of the two predefines buffers should be the same. If
313/// not, then some command-line option changed the preprocessor state
314/// and we must reject the PCH file.
315///
316/// \param PCHPredef The start of the predefines buffer in the PCH
317/// file.
318///
319/// \param PCHPredefLen The length of the predefines buffer in the PCH
320/// file.
321///
322/// \param PCHBufferID The FileID for the PCH predefines buffer.
323///
324/// \returns true if there was a mismatch (in which case the PCH file
325/// should be ignored), or false otherwise.
326bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
327 unsigned PCHPredefLen,
328 FileID PCHBufferID) {
329 const char *Predef = PP.getPredefines().c_str();
330 unsigned PredefLen = PP.getPredefines().size();
331
332 // If the two predefines buffers compare equal, we're done!.
333 if (PredefLen == PCHPredefLen &&
334 strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
335 return false;
336
337 // The predefines buffers are different. Produce a reasonable
338 // diagnostic showing where they are different.
339
340 // The source locations (potentially in the two different predefines
341 // buffers)
342 SourceLocation Loc1, Loc2;
343 SourceManager &SourceMgr = PP.getSourceManager();
344
345 // Create a source buffer for our predefines string, so
346 // that we can build a diagnostic that points into that
347 // source buffer.
348 FileID BufferID;
349 if (Predef && Predef[0]) {
350 llvm::MemoryBuffer *Buffer
351 = llvm::MemoryBuffer::getMemBuffer(Predef, Predef + PredefLen,
352 "<built-in>");
353 BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
354 }
355
356 unsigned MinLen = std::min(PredefLen, PCHPredefLen);
357 std::pair<const char *, const char *> Locations
358 = std::mismatch(Predef, Predef + MinLen, PCHPredef);
359
360 if (Locations.first != Predef + MinLen) {
361 // We found the location in the two buffers where there is a
362 // difference. Form source locations to point there (in both
363 // buffers).
364 unsigned Offset = Locations.first - Predef;
365 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
366 .getFileLocWithOffset(Offset);
367 Loc2 = SourceMgr.getLocForStartOfFile(PCHBufferID)
368 .getFileLocWithOffset(Offset);
369 } else if (PredefLen > PCHPredefLen) {
370 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
371 .getFileLocWithOffset(MinLen);
372 } else {
373 Loc1 = SourceMgr.getLocForStartOfFile(PCHBufferID)
374 .getFileLocWithOffset(MinLen);
375 }
376
377 Diag(Loc1, diag::warn_pch_preprocessor);
378 if (Loc2.isValid())
379 Diag(Loc2, diag::note_predef_in_pch);
380 Diag(diag::note_ignoring_pch) << FileName;
381 return true;
382}
383
Douglas Gregor6cc5d192009-04-27 18:38:38 +0000384//===----------------------------------------------------------------------===//
385// Source Manager Deserialization
386//===----------------------------------------------------------------------===//
387
Douglas Gregor635f97f2009-04-13 16:31:14 +0000388/// \brief Read the line table in the source manager block.
389/// \returns true if ther was an error.
390static bool ParseLineTable(SourceManager &SourceMgr,
391 llvm::SmallVectorImpl<uint64_t> &Record) {
392 unsigned Idx = 0;
393 LineTableInfo &LineTable = SourceMgr.getLineTable();
394
395 // Parse the file names
Douglas Gregor183ad602009-04-13 17:12:42 +0000396 std::map<int, int> FileIDs;
397 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregor635f97f2009-04-13 16:31:14 +0000398 // Extract the file name
399 unsigned FilenameLen = Record[Idx++];
400 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
401 Idx += FilenameLen;
Douglas Gregor183ad602009-04-13 17:12:42 +0000402 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
403 Filename.size());
Douglas Gregor635f97f2009-04-13 16:31:14 +0000404 }
405
406 // Parse the line entries
407 std::vector<LineEntry> Entries;
408 while (Idx < Record.size()) {
Douglas Gregor183ad602009-04-13 17:12:42 +0000409 int FID = FileIDs[Record[Idx++]];
Douglas Gregor635f97f2009-04-13 16:31:14 +0000410
411 // Extract the line entries
412 unsigned NumEntries = Record[Idx++];
413 Entries.clear();
414 Entries.reserve(NumEntries);
415 for (unsigned I = 0; I != NumEntries; ++I) {
416 unsigned FileOffset = Record[Idx++];
417 unsigned LineNo = Record[Idx++];
418 int FilenameID = Record[Idx++];
419 SrcMgr::CharacteristicKind FileKind
420 = (SrcMgr::CharacteristicKind)Record[Idx++];
421 unsigned IncludeOffset = Record[Idx++];
422 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
423 FileKind, IncludeOffset));
424 }
425 LineTable.AddEntry(FID, Entries);
426 }
427
428 return false;
429}
430
Douglas Gregor6cc5d192009-04-27 18:38:38 +0000431namespace {
432
433class VISIBILITY_HIDDEN PCHStatData {
434public:
435 const bool hasStat;
436 const ino_t ino;
437 const dev_t dev;
438 const mode_t mode;
439 const time_t mtime;
440 const off_t size;
441
442 PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
443 : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
444
445 PCHStatData()
446 : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
447};
448
449class VISIBILITY_HIDDEN PCHStatLookupTrait {
450 public:
451 typedef const char *external_key_type;
452 typedef const char *internal_key_type;
453
454 typedef PCHStatData data_type;
455
456 static unsigned ComputeHash(const char *path) {
457 return BernsteinHash(path);
458 }
459
460 static internal_key_type GetInternalKey(const char *path) { return path; }
461
462 static bool EqualKey(internal_key_type a, internal_key_type b) {
463 return strcmp(a, b) == 0;
464 }
465
466 static std::pair<unsigned, unsigned>
467 ReadKeyDataLength(const unsigned char*& d) {
468 unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
469 unsigned DataLen = (unsigned) *d++;
470 return std::make_pair(KeyLen + 1, DataLen);
471 }
472
473 static internal_key_type ReadKey(const unsigned char *d, unsigned) {
474 return (const char *)d;
475 }
476
477 static data_type ReadData(const internal_key_type, const unsigned char *d,
478 unsigned /*DataLen*/) {
479 using namespace clang::io;
480
481 if (*d++ == 1)
482 return data_type();
483
484 ino_t ino = (ino_t) ReadUnalignedLE32(d);
485 dev_t dev = (dev_t) ReadUnalignedLE32(d);
486 mode_t mode = (mode_t) ReadUnalignedLE16(d);
487 time_t mtime = (time_t) ReadUnalignedLE64(d);
488 off_t size = (off_t) ReadUnalignedLE64(d);
489 return data_type(ino, dev, mode, mtime, size);
490 }
491};
492
493/// \brief stat() cache for precompiled headers.
494///
495/// This cache is very similar to the stat cache used by pretokenized
496/// headers.
497class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache {
498 typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
499 CacheTy *Cache;
500
501 unsigned &NumStatHits, &NumStatMisses;
502public:
503 PCHStatCache(const unsigned char *Buckets,
504 const unsigned char *Base,
505 unsigned &NumStatHits,
506 unsigned &NumStatMisses)
507 : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
508 Cache = CacheTy::Create(Buckets, Base);
509 }
510
511 ~PCHStatCache() { delete Cache; }
512
513 int stat(const char *path, struct stat *buf) {
514 // Do the lookup for the file's data in the PCH file.
515 CacheTy::iterator I = Cache->find(path);
516
517 // If we don't get a hit in the PCH file just forward to 'stat'.
518 if (I == Cache->end()) {
519 ++NumStatMisses;
520 return ::stat(path, buf);
521 }
522
523 ++NumStatHits;
524 PCHStatData Data = *I;
525
526 if (!Data.hasStat)
527 return 1;
528
529 buf->st_ino = Data.ino;
530 buf->st_dev = Data.dev;
531 buf->st_mtime = Data.mtime;
532 buf->st_mode = Data.mode;
533 buf->st_size = Data.size;
534 return 0;
535 }
536};
537} // end anonymous namespace
538
539
Douglas Gregorab1cef72009-04-10 03:52:48 +0000540/// \brief Read the source manager block
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000541PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregorab1cef72009-04-10 03:52:48 +0000542 using namespace SrcMgr;
Douglas Gregor32e231c2009-04-27 06:38:32 +0000543
544 // Set the source-location entry cursor to the current position in
545 // the stream. This cursor will be used to read the contents of the
546 // source manager block initially, and then lazily read
547 // source-location entries as needed.
548 SLocEntryCursor = Stream;
549
550 // The stream itself is going to skip over the source manager block.
551 if (Stream.SkipBlock()) {
552 Error("Malformed block record");
553 return Failure;
554 }
555
556 // Enter the source manager block.
557 if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000558 Error("Malformed source manager block record");
559 return Failure;
560 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000561
Chris Lattner270d29a2009-04-27 21:45:14 +0000562 SourceManager &SourceMgr = PP.getSourceManager();
Douglas Gregorab1cef72009-04-10 03:52:48 +0000563 RecordData Record;
Douglas Gregorf6e1fb22009-04-26 00:07:37 +0000564 unsigned NumHeaderInfos = 0;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000565 while (true) {
Douglas Gregor32e231c2009-04-27 06:38:32 +0000566 unsigned Code = SLocEntryCursor.ReadCode();
Douglas Gregorab1cef72009-04-10 03:52:48 +0000567 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor32e231c2009-04-27 06:38:32 +0000568 if (SLocEntryCursor.ReadBlockEnd()) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000569 Error("Error at end of Source Manager block");
570 return Failure;
571 }
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000572 return Success;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000573 }
574
575 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
576 // No known subblocks, always skip them.
Douglas Gregor32e231c2009-04-27 06:38:32 +0000577 SLocEntryCursor.ReadSubBlockID();
578 if (SLocEntryCursor.SkipBlock()) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000579 Error("Malformed block record");
580 return Failure;
581 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000582 continue;
583 }
584
585 if (Code == llvm::bitc::DEFINE_ABBREV) {
Douglas Gregor32e231c2009-04-27 06:38:32 +0000586 SLocEntryCursor.ReadAbbrevRecord();
Douglas Gregorab1cef72009-04-10 03:52:48 +0000587 continue;
588 }
589
590 // Read a record.
591 const char *BlobStart;
592 unsigned BlobLen;
593 Record.clear();
Douglas Gregor32e231c2009-04-27 06:38:32 +0000594 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
Douglas Gregorab1cef72009-04-10 03:52:48 +0000595 default: // Default behavior: ignore.
596 break;
597
Chris Lattnere1be6022009-04-14 23:22:57 +0000598 case pch::SM_LINE_TABLE:
Douglas Gregor635f97f2009-04-13 16:31:14 +0000599 if (ParseLineTable(SourceMgr, Record))
600 return Failure;
Chris Lattnere1be6022009-04-14 23:22:57 +0000601 break;
Douglas Gregorf6e1fb22009-04-26 00:07:37 +0000602
603 case pch::SM_HEADER_FILE_INFO: {
604 HeaderFileInfo HFI;
605 HFI.isImport = Record[0];
606 HFI.DirInfo = Record[1];
607 HFI.NumIncludes = Record[2];
608 HFI.ControllingMacroID = Record[3];
609 PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
610 break;
611 }
Douglas Gregor32e231c2009-04-27 06:38:32 +0000612
613 case pch::SM_SLOC_FILE_ENTRY:
614 case pch::SM_SLOC_BUFFER_ENTRY:
615 case pch::SM_SLOC_INSTANTIATION_ENTRY:
616 // Once we hit one of the source location entries, we're done.
617 return Success;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000618 }
619 }
620}
621
Douglas Gregor32e231c2009-04-27 06:38:32 +0000622/// \brief Read in the source location entry with the given ID.
623PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
624 if (ID == 0)
625 return Success;
626
627 if (ID > TotalNumSLocEntries) {
628 Error("source location entry ID out-of-range for PCH file");
629 return Failure;
630 }
631
632 ++NumSLocEntriesRead;
633 SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
634 unsigned Code = SLocEntryCursor.ReadCode();
635 if (Code == llvm::bitc::END_BLOCK ||
636 Code == llvm::bitc::ENTER_SUBBLOCK ||
637 Code == llvm::bitc::DEFINE_ABBREV) {
638 Error("incorrectly-formatted source location entry in PCH file");
639 return Failure;
640 }
641
Chris Lattner270d29a2009-04-27 21:45:14 +0000642 SourceManager &SourceMgr = PP.getSourceManager();
Douglas Gregor32e231c2009-04-27 06:38:32 +0000643 RecordData Record;
644 const char *BlobStart;
645 unsigned BlobLen;
646 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
647 default:
648 Error("incorrectly-formatted source location entry in PCH file");
649 return Failure;
650
651 case pch::SM_SLOC_FILE_ENTRY: {
652 const FileEntry *File
653 = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
654 // FIXME: Error recovery if file cannot be found.
655 FileID FID = SourceMgr.createFileID(File,
656 SourceLocation::getFromRawEncoding(Record[1]),
657 (SrcMgr::CharacteristicKind)Record[2],
658 ID, Record[0]);
659 if (Record[3])
660 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
661 .setHasLineDirectives();
662
663 break;
664 }
665
666 case pch::SM_SLOC_BUFFER_ENTRY: {
667 const char *Name = BlobStart;
668 unsigned Offset = Record[0];
669 unsigned Code = SLocEntryCursor.ReadCode();
670 Record.clear();
671 unsigned RecCode
672 = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
673 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
674 (void)RecCode;
675 llvm::MemoryBuffer *Buffer
676 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
677 BlobStart + BlobLen - 1,
678 Name);
679 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
680
681 if (strcmp(Name, "<built-in>") == 0
682 && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID))
683 return IgnorePCH;
684
685 break;
686 }
687
688 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
689 SourceLocation SpellingLoc
690 = SourceLocation::getFromRawEncoding(Record[1]);
691 SourceMgr.createInstantiationLoc(SpellingLoc,
692 SourceLocation::getFromRawEncoding(Record[2]),
693 SourceLocation::getFromRawEncoding(Record[3]),
694 Record[4],
695 ID,
696 Record[0]);
697 break;
698 }
699 }
700
701 return Success;
702}
703
Chris Lattner4fc71eb2009-04-27 01:05:14 +0000704/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
705/// specified cursor. Read the abbreviations that are at the top of the block
706/// and then leave the cursor pointing into the block.
707bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
708 unsigned BlockID) {
709 if (Cursor.EnterSubBlock(BlockID)) {
710 Error("Malformed block record");
711 return Failure;
712 }
713
Chris Lattner4fc71eb2009-04-27 01:05:14 +0000714 while (true) {
715 unsigned Code = Cursor.ReadCode();
716
717 // We expect all abbrevs to be at the start of the block.
718 if (Code != llvm::bitc::DEFINE_ABBREV)
719 return false;
720 Cursor.ReadAbbrevRecord();
721 }
722}
723
Douglas Gregore0ad2dd2009-04-21 23:56:24 +0000724void PCHReader::ReadMacroRecord(uint64_t Offset) {
725 // Keep track of where we are in the stream, then jump back there
726 // after reading this macro.
727 SavedStreamPosition SavedPosition(Stream);
728
729 Stream.JumpToBit(Offset);
730 RecordData Record;
731 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
732 MacroInfo *Macro = 0;
Steve Naroffcda68f22009-04-24 20:03:17 +0000733
Douglas Gregore0ad2dd2009-04-21 23:56:24 +0000734 while (true) {
735 unsigned Code = Stream.ReadCode();
736 switch (Code) {
737 case llvm::bitc::END_BLOCK:
738 return;
739
740 case llvm::bitc::ENTER_SUBBLOCK:
741 // No known subblocks, always skip them.
742 Stream.ReadSubBlockID();
743 if (Stream.SkipBlock()) {
744 Error("Malformed block record");
745 return;
746 }
747 continue;
748
749 case llvm::bitc::DEFINE_ABBREV:
750 Stream.ReadAbbrevRecord();
751 continue;
752 default: break;
753 }
754
755 // Read a record.
756 Record.clear();
757 pch::PreprocessorRecordTypes RecType =
758 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
759 switch (RecType) {
Douglas Gregore0ad2dd2009-04-21 23:56:24 +0000760 case pch::PP_MACRO_OBJECT_LIKE:
761 case pch::PP_MACRO_FUNCTION_LIKE: {
762 // If we already have a macro, that means that we've hit the end
763 // of the definition of the macro we were looking for. We're
764 // done.
765 if (Macro)
766 return;
767
768 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
769 if (II == 0) {
770 Error("Macro must have a name");
771 return;
772 }
773 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
774 bool isUsed = Record[2];
775
776 MacroInfo *MI = PP.AllocateMacroInfo(Loc);
777 MI->setIsUsed(isUsed);
778
779 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
780 // Decode function-like macro info.
781 bool isC99VarArgs = Record[3];
782 bool isGNUVarArgs = Record[4];
783 MacroArgs.clear();
784 unsigned NumArgs = Record[5];
785 for (unsigned i = 0; i != NumArgs; ++i)
786 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
787
788 // Install function-like macro info.
789 MI->setIsFunctionLike();
790 if (isC99VarArgs) MI->setIsC99Varargs();
791 if (isGNUVarArgs) MI->setIsGNUVarargs();
792 MI->setArgumentList(&MacroArgs[0], MacroArgs.size(),
793 PP.getPreprocessorAllocator());
794 }
795
796 // Finally, install the macro.
797 PP.setMacroInfo(II, MI);
798
799 // Remember that we saw this macro last so that we add the tokens that
800 // form its body to it.
801 Macro = MI;
802 ++NumMacrosRead;
803 break;
804 }
805
806 case pch::PP_TOKEN: {
807 // If we see a TOKEN before a PP_MACRO_*, then the file is
808 // erroneous, just pretend we didn't see this.
809 if (Macro == 0) break;
810
811 Token Tok;
812 Tok.startToken();
813 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
814 Tok.setLength(Record[1]);
815 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
816 Tok.setIdentifierInfo(II);
817 Tok.setKind((tok::TokenKind)Record[3]);
818 Tok.setFlag((Token::TokenFlags)Record[4]);
819 Macro->AddTokenToBody(Tok);
820 break;
821 }
Steve Naroffcda68f22009-04-24 20:03:17 +0000822 }
Douglas Gregore0ad2dd2009-04-21 23:56:24 +0000823 }
824}
825
Douglas Gregorc713da92009-04-21 22:25:48 +0000826PCHReader::PCHReadResult
Douglas Gregorf6e1fb22009-04-26 00:07:37 +0000827PCHReader::ReadPCHBlock() {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000828 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
829 Error("Malformed block record");
830 return Failure;
831 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000832
833 // Read all of the records and blocks for the PCH file.
Douglas Gregorac8f2802009-04-10 17:25:41 +0000834 RecordData Record;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000835 while (!Stream.AtEndOfStream()) {
836 unsigned Code = Stream.ReadCode();
837 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000838 if (Stream.ReadBlockEnd()) {
839 Error("Error at end of module block");
840 return Failure;
841 }
Chris Lattner29241862009-04-11 21:15:38 +0000842
Douglas Gregor179cfb12009-04-10 20:39:37 +0000843 return Success;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000844 }
845
846 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
847 switch (Stream.ReadSubBlockID()) {
Douglas Gregorc34897d2009-04-09 22:27:44 +0000848 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
849 default: // Skip unknown content.
Douglas Gregor179cfb12009-04-10 20:39:37 +0000850 if (Stream.SkipBlock()) {
851 Error("Malformed block record");
852 return Failure;
853 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000854 break;
855
Chris Lattner4fc71eb2009-04-27 01:05:14 +0000856 case pch::DECLS_BLOCK_ID:
857 // We lazily load the decls block, but we want to set up the
858 // DeclsCursor cursor to point into it. Clone our current bitcode
859 // cursor to it, enter the block and read the abbrevs in that block.
860 // With the main cursor, we just skip over it.
861 DeclsCursor = Stream;
862 if (Stream.SkipBlock() || // Skip with the main cursor.
863 // Read the abbrevs.
864 ReadBlockAbbrevs(DeclsCursor, pch::DECLS_BLOCK_ID)) {
865 Error("Malformed block record");
866 return Failure;
867 }
868 break;
869
Chris Lattner29241862009-04-11 21:15:38 +0000870 case pch::PREPROCESSOR_BLOCK_ID:
Chris Lattner29241862009-04-11 21:15:38 +0000871 if (Stream.SkipBlock()) {
872 Error("Malformed block record");
873 return Failure;
874 }
875 break;
Steve Naroff9e84d782009-04-23 10:39:46 +0000876
Douglas Gregorab1cef72009-04-10 03:52:48 +0000877 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000878 switch (ReadSourceManagerBlock()) {
879 case Success:
880 break;
881
882 case Failure:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000883 Error("Malformed source manager block");
884 return Failure;
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000885
886 case IgnorePCH:
887 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000888 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000889 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000890 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000891 continue;
892 }
893
894 if (Code == llvm::bitc::DEFINE_ABBREV) {
895 Stream.ReadAbbrevRecord();
896 continue;
897 }
898
899 // Read and process a record.
900 Record.clear();
Douglas Gregorb5887f32009-04-10 21:16:55 +0000901 const char *BlobStart = 0;
902 unsigned BlobLen = 0;
903 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
904 &BlobStart, &BlobLen)) {
Douglas Gregorac8f2802009-04-10 17:25:41 +0000905 default: // Default behavior: ignore.
906 break;
907
908 case pch::TYPE_OFFSET:
Douglas Gregor24a224c2009-04-25 18:35:21 +0000909 if (!TypesLoaded.empty()) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000910 Error("Duplicate TYPE_OFFSET record in PCH file");
911 return Failure;
912 }
Chris Lattnerea332f32009-04-27 18:24:17 +0000913 TypeOffsets = (const uint32_t *)BlobStart;
Douglas Gregor24a224c2009-04-25 18:35:21 +0000914 TypesLoaded.resize(Record[0]);
Douglas Gregorac8f2802009-04-10 17:25:41 +0000915 break;
916
917 case pch::DECL_OFFSET:
Douglas Gregor24a224c2009-04-25 18:35:21 +0000918 if (!DeclsLoaded.empty()) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000919 Error("Duplicate DECL_OFFSET record in PCH file");
920 return Failure;
921 }
Chris Lattnerea332f32009-04-27 18:24:17 +0000922 DeclOffsets = (const uint32_t *)BlobStart;
Douglas Gregor24a224c2009-04-25 18:35:21 +0000923 DeclsLoaded.resize(Record[0]);
Douglas Gregorac8f2802009-04-10 17:25:41 +0000924 break;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000925
926 case pch::LANGUAGE_OPTIONS:
927 if (ParseLanguageOptions(Record))
928 return IgnorePCH;
929 break;
Douglas Gregorb5887f32009-04-10 21:16:55 +0000930
Douglas Gregorb7064742009-04-27 22:23:34 +0000931 case pch::METADATA: {
932 if (Record[0] != pch::VERSION_MAJOR) {
933 Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
934 : diag::warn_pch_version_too_new);
935 return IgnorePCH;
936 }
937
Douglas Gregorb5887f32009-04-10 21:16:55 +0000938 std::string TargetTriple(BlobStart, BlobLen);
Chris Lattner270d29a2009-04-27 21:45:14 +0000939 if (TargetTriple != PP.getTargetInfo().getTargetTriple()) {
Douglas Gregorb5887f32009-04-10 21:16:55 +0000940 Diag(diag::warn_pch_target_triple)
Chris Lattner270d29a2009-04-27 21:45:14 +0000941 << TargetTriple << PP.getTargetInfo().getTargetTriple();
Douglas Gregorb5887f32009-04-10 21:16:55 +0000942 Diag(diag::note_ignoring_pch) << FileName;
943 return IgnorePCH;
944 }
945 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000946 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000947
948 case pch::IDENTIFIER_TABLE:
Douglas Gregorc713da92009-04-21 22:25:48 +0000949 IdentifierTableData = BlobStart;
Douglas Gregorde44c9f2009-04-25 19:10:14 +0000950 if (Record[0]) {
951 IdentifierLookupTable
952 = PCHIdentifierLookupTable::Create(
Douglas Gregorc713da92009-04-21 22:25:48 +0000953 (const unsigned char *)IdentifierTableData + Record[0],
954 (const unsigned char *)IdentifierTableData,
955 PCHIdentifierLookupTrait(*this));
Douglas Gregorde44c9f2009-04-25 19:10:14 +0000956 PP.getIdentifierTable().setExternalIdentifierLookup(this);
957 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000958 break;
959
960 case pch::IDENTIFIER_OFFSET:
Douglas Gregorde44c9f2009-04-25 19:10:14 +0000961 if (!IdentifiersLoaded.empty()) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000962 Error("Duplicate IDENTIFIER_OFFSET record in PCH file");
963 return Failure;
964 }
Douglas Gregorde44c9f2009-04-25 19:10:14 +0000965 IdentifierOffsets = (const uint32_t *)BlobStart;
966 IdentifiersLoaded.resize(Record[0]);
Douglas Gregoreccb51d2009-04-25 23:30:02 +0000967 PP.getHeaderSearchInfo().SetExternalLookup(this);
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000968 break;
Douglas Gregor631f6c62009-04-14 00:24:19 +0000969
970 case pch::EXTERNAL_DEFINITIONS:
971 if (!ExternalDefinitions.empty()) {
972 Error("Duplicate EXTERNAL_DEFINITIONS record in PCH file");
973 return Failure;
974 }
975 ExternalDefinitions.swap(Record);
976 break;
Douglas Gregor456e0952009-04-17 22:13:46 +0000977
Douglas Gregore01ad442009-04-18 05:55:16 +0000978 case pch::SPECIAL_TYPES:
979 SpecialTypes.swap(Record);
980 break;
981
Douglas Gregor456e0952009-04-17 22:13:46 +0000982 case pch::STATISTICS:
983 TotalNumStatements = Record[0];
Douglas Gregore0ad2dd2009-04-21 23:56:24 +0000984 TotalNumMacros = Record[1];
Douglas Gregoraf136d92009-04-22 22:34:57 +0000985 TotalLexicalDeclContexts = Record[2];
986 TotalVisibleDeclContexts = Record[3];
Douglas Gregor456e0952009-04-17 22:13:46 +0000987 break;
Douglas Gregor32e231c2009-04-27 06:38:32 +0000988
Douglas Gregor77b2cd52009-04-22 22:02:47 +0000989 case pch::TENTATIVE_DEFINITIONS:
990 if (!TentativeDefinitions.empty()) {
991 Error("Duplicate TENTATIVE_DEFINITIONS record in PCH file");
992 return Failure;
993 }
994 TentativeDefinitions.swap(Record);
995 break;
Douglas Gregor062d9482009-04-22 22:18:58 +0000996
997 case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
998 if (!LocallyScopedExternalDecls.empty()) {
999 Error("Duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
1000 return Failure;
1001 }
1002 LocallyScopedExternalDecls.swap(Record);
1003 break;
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001004
Douglas Gregor2d711832009-04-25 17:48:32 +00001005 case pch::SELECTOR_OFFSETS:
1006 SelectorOffsets = (const uint32_t *)BlobStart;
1007 TotalNumSelectors = Record[0];
1008 SelectorsLoaded.resize(TotalNumSelectors);
1009 break;
1010
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001011 case pch::METHOD_POOL:
Douglas Gregor2d711832009-04-25 17:48:32 +00001012 MethodPoolLookupTableData = (const unsigned char *)BlobStart;
1013 if (Record[0])
1014 MethodPoolLookupTable
1015 = PCHMethodPoolLookupTable::Create(
1016 MethodPoolLookupTableData + Record[0],
1017 MethodPoolLookupTableData,
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001018 PCHMethodPoolLookupTrait(*this));
Douglas Gregor2d711832009-04-25 17:48:32 +00001019 TotalSelectorsInMethodPool = Record[1];
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001020 break;
Douglas Gregorf6e1fb22009-04-26 00:07:37 +00001021
1022 case pch::PP_COUNTER_VALUE:
1023 if (!Record.empty())
1024 PP.setCounterValue(Record[0]);
1025 break;
Douglas Gregor32e231c2009-04-27 06:38:32 +00001026
1027 case pch::SOURCE_LOCATION_OFFSETS:
Chris Lattner93307da2009-04-27 19:01:47 +00001028 SLocOffsets = (const uint32_t *)BlobStart;
Douglas Gregor32e231c2009-04-27 06:38:32 +00001029 TotalNumSLocEntries = Record[0];
1030 PP.getSourceManager().PreallocateSLocEntries(this,
1031 TotalNumSLocEntries,
1032 Record[1]);
1033 break;
1034
1035 case pch::SOURCE_LOCATION_PRELOADS:
1036 for (unsigned I = 0, N = Record.size(); I != N; ++I) {
1037 PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
1038 if (Result != Success)
1039 return Result;
1040 }
1041 break;
Douglas Gregor6cc5d192009-04-27 18:38:38 +00001042
1043 case pch::STAT_CACHE:
1044 PP.getFileManager().setStatCache(
1045 new PCHStatCache((const unsigned char *)BlobStart + Record[0],
1046 (const unsigned char *)BlobStart,
1047 NumStatHits, NumStatMisses));
1048 break;
Douglas Gregorb36b20d2009-04-27 20:06:05 +00001049
1050 case pch::EXT_VECTOR_DECLS:
1051 if (!ExtVectorDecls.empty()) {
1052 Error("Duplicate EXT_VECTOR_DECLS record in PCH file");
1053 return Failure;
1054 }
1055 ExtVectorDecls.swap(Record);
1056 break;
1057
1058 case pch::OBJC_CATEGORY_IMPLEMENTATIONS:
1059 if (!ObjCCategoryImpls.empty()) {
1060 Error("Duplicate OBJC_CATEGORY_IMPLEMENTATIONS record in PCH file");
1061 return Failure;
1062 }
1063 ObjCCategoryImpls.swap(Record);
1064 break;
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001065 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001066 }
Douglas Gregor179cfb12009-04-10 20:39:37 +00001067 Error("Premature end of bitstream");
1068 return Failure;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001069}
1070
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001071PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor179cfb12009-04-10 20:39:37 +00001072 // Set the PCH file name.
1073 this->FileName = FileName;
1074
Douglas Gregorc34897d2009-04-09 22:27:44 +00001075 // Open the PCH file.
1076 std::string ErrStr;
1077 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001078 if (!Buffer) {
1079 Error(ErrStr.c_str());
1080 return IgnorePCH;
1081 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001082
1083 // Initialize the stream
Chris Lattner587788a2009-04-26 20:59:20 +00001084 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
1085 (const unsigned char *)Buffer->getBufferEnd());
1086 Stream.init(StreamFile);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001087
1088 // Sniff for the signature.
1089 if (Stream.Read(8) != 'C' ||
1090 Stream.Read(8) != 'P' ||
1091 Stream.Read(8) != 'C' ||
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001092 Stream.Read(8) != 'H') {
1093 Error("Not a PCH file");
1094 return IgnorePCH;
1095 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001096
Douglas Gregorc34897d2009-04-09 22:27:44 +00001097 while (!Stream.AtEndOfStream()) {
1098 unsigned Code = Stream.ReadCode();
1099
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001100 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
1101 Error("Invalid record at top-level");
1102 return Failure;
1103 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001104
1105 unsigned BlockID = Stream.ReadSubBlockID();
Douglas Gregorc713da92009-04-21 22:25:48 +00001106
Douglas Gregorc34897d2009-04-09 22:27:44 +00001107 // We only know the PCH subblock ID.
1108 switch (BlockID) {
1109 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001110 if (Stream.ReadBlockInfoBlock()) {
1111 Error("Malformed BlockInfoBlock");
1112 return Failure;
1113 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001114 break;
1115 case pch::PCH_BLOCK_ID:
Douglas Gregorf6e1fb22009-04-26 00:07:37 +00001116 switch (ReadPCHBlock()) {
Douglas Gregor179cfb12009-04-10 20:39:37 +00001117 case Success:
1118 break;
1119
1120 case Failure:
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001121 return Failure;
Douglas Gregor179cfb12009-04-10 20:39:37 +00001122
1123 case IgnorePCH:
Douglas Gregorb5887f32009-04-10 21:16:55 +00001124 // FIXME: We could consider reading through to the end of this
1125 // PCH block, skipping subblocks, to see if there are other
1126 // PCH blocks elsewhere.
Douglas Gregor57885192009-04-27 21:28:04 +00001127
1128 // Clear out any preallocated source location entries, so that
1129 // the source manager does not try to resolve them later.
1130 PP.getSourceManager().ClearPreallocatedSLocEntries();
1131
1132 // Remove the stat cache.
1133 PP.getFileManager().setStatCache(0);
1134
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001135 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +00001136 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001137 break;
1138 default:
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001139 if (Stream.SkipBlock()) {
1140 Error("Malformed block record");
1141 return Failure;
1142 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001143 break;
1144 }
1145 }
1146
1147 // Load the translation unit declaration
Chris Lattner270d29a2009-04-27 21:45:14 +00001148 if (Context)
1149 ReadDeclRecord(DeclOffsets[0], 0);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001150
Douglas Gregorc713da92009-04-21 22:25:48 +00001151 // Initialization of builtins and library builtins occurs before the
1152 // PCH file is read, so there may be some identifiers that were
1153 // loaded into the IdentifierTable before we intercepted the
1154 // creation of identifiers. Iterate through the list of known
1155 // identifiers and determine whether we have to establish
1156 // preprocessor definitions or top-level identifier declaration
1157 // chains for those identifiers.
1158 //
1159 // We copy the IdentifierInfo pointers to a small vector first,
1160 // since de-serializing declarations or macro definitions can add
1161 // new entries into the identifier table, invalidating the
1162 // iterators.
1163 llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
1164 for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
1165 IdEnd = PP.getIdentifierTable().end();
1166 Id != IdEnd; ++Id)
1167 Identifiers.push_back(Id->second);
1168 PCHIdentifierLookupTable *IdTable
1169 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1170 for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
1171 IdentifierInfo *II = Identifiers[I];
1172 // Look in the on-disk hash table for an entry for
1173 PCHIdentifierLookupTrait Info(*this, II);
1174 std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
1175 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
1176 if (Pos == IdTable->end())
1177 continue;
1178
1179 // Dereferencing the iterator has the effect of populating the
1180 // IdentifierInfo node with the various declarations it needs.
1181 (void)*Pos;
1182 }
1183
Douglas Gregore01ad442009-04-18 05:55:16 +00001184 // Load the special types.
Chris Lattner270d29a2009-04-27 21:45:14 +00001185 if (Context) {
1186 Context->setBuiltinVaListType(
1187 GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
1188 if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
1189 Context->setObjCIdType(GetType(Id));
1190 if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
1191 Context->setObjCSelType(GetType(Sel));
1192 if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
1193 Context->setObjCProtoType(GetType(Proto));
1194 if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
1195 Context->setObjCClassType(GetType(Class));
1196 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
1197 Context->setCFConstantStringType(GetType(String));
1198 if (unsigned FastEnum
1199 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
1200 Context->setObjCFastEnumerationStateType(GetType(FastEnum));
1201 }
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001202
Douglas Gregorc713da92009-04-21 22:25:48 +00001203 return Success;
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001204}
1205
Douglas Gregor179cfb12009-04-10 20:39:37 +00001206/// \brief Parse the record that corresponds to a LangOptions data
1207/// structure.
1208///
1209/// This routine compares the language options used to generate the
1210/// PCH file against the language options set for the current
1211/// compilation. For each option, we classify differences between the
1212/// two compiler states as either "benign" or "important". Benign
1213/// differences don't matter, and we accept them without complaint
1214/// (and without modifying the language options). Differences between
1215/// the states for important options cause the PCH file to be
1216/// unusable, so we emit a warning and return true to indicate that
1217/// there was an error.
1218///
1219/// \returns true if the PCH file is unacceptable, false otherwise.
1220bool PCHReader::ParseLanguageOptions(
1221 const llvm::SmallVectorImpl<uint64_t> &Record) {
Chris Lattner270d29a2009-04-27 21:45:14 +00001222 const LangOptions &LangOpts = PP.getLangOptions();
Douglas Gregor179cfb12009-04-10 20:39:37 +00001223#define PARSE_LANGOPT_BENIGN(Option) ++Idx
1224#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
1225 if (Record[Idx] != LangOpts.Option) { \
1226 Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
1227 Diag(diag::note_ignoring_pch) << FileName; \
1228 return true; \
1229 } \
1230 ++Idx
1231
1232 unsigned Idx = 0;
1233 PARSE_LANGOPT_BENIGN(Trigraphs);
1234 PARSE_LANGOPT_BENIGN(BCPLComment);
1235 PARSE_LANGOPT_BENIGN(DollarIdents);
1236 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
1237 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
1238 PARSE_LANGOPT_BENIGN(ImplicitInt);
1239 PARSE_LANGOPT_BENIGN(Digraphs);
1240 PARSE_LANGOPT_BENIGN(HexFloats);
1241 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
1242 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
1243 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
1244 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
1245 PARSE_LANGOPT_IMPORTANT(NoExtensions, diag::warn_pch_extensions);
1246 PARSE_LANGOPT_BENIGN(CXXOperatorName);
1247 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
1248 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
1249 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
1250 PARSE_LANGOPT_BENIGN(PascalStrings);
1251 PARSE_LANGOPT_BENIGN(Boolean);
1252 PARSE_LANGOPT_BENIGN(WritableStrings);
1253 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
1254 diag::warn_pch_lax_vector_conversions);
1255 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
1256 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
1257 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
1258 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
1259 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
1260 diag::warn_pch_thread_safe_statics);
1261 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
1262 PARSE_LANGOPT_BENIGN(EmitAllDecls);
1263 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
1264 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
1265 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
1266 diag::warn_pch_heinous_extensions);
1267 // FIXME: Most of the options below are benign if the macro wasn't
1268 // used. Unfortunately, this means that a PCH compiled without
1269 // optimization can't be used with optimization turned on, even
1270 // though the only thing that changes is whether __OPTIMIZE__ was
1271 // defined... but if __OPTIMIZE__ never showed up in the header, it
1272 // doesn't matter. We could consider making this some special kind
1273 // of check.
1274 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
1275 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
1276 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
1277 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
1278 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
1279 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
1280 if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
1281 Diag(diag::warn_pch_gc_mode)
1282 << (unsigned)Record[Idx] << LangOpts.getGCMode();
1283 Diag(diag::note_ignoring_pch) << FileName;
1284 return true;
1285 }
1286 ++Idx;
1287 PARSE_LANGOPT_BENIGN(getVisibilityMode());
1288 PARSE_LANGOPT_BENIGN(InstantiationDepth);
1289#undef PARSE_LANGOPT_IRRELEVANT
1290#undef PARSE_LANGOPT_BENIGN
1291
1292 return false;
1293}
1294
Douglas Gregorc34897d2009-04-09 22:27:44 +00001295/// \brief Read and return the type at the given offset.
1296///
1297/// This routine actually reads the record corresponding to the type
1298/// at the given offset in the bitstream. It is a helper routine for
1299/// GetType, which deals with reading type IDs.
1300QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001301 // Keep track of where we are in the stream, then jump back there
1302 // after reading this type.
1303 SavedStreamPosition SavedPosition(Stream);
1304
Douglas Gregorc34897d2009-04-09 22:27:44 +00001305 Stream.JumpToBit(Offset);
1306 RecordData Record;
1307 unsigned Code = Stream.ReadCode();
1308 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
Douglas Gregorbdd4ba52009-04-15 22:00:08 +00001309 case pch::TYPE_EXT_QUAL: {
1310 assert(Record.size() == 3 &&
1311 "Incorrect encoding of extended qualifier type");
1312 QualType Base = GetType(Record[0]);
1313 QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1];
1314 unsigned AddressSpace = Record[2];
1315
1316 QualType T = Base;
1317 if (GCAttr != QualType::GCNone)
Chris Lattner270d29a2009-04-27 21:45:14 +00001318 T = Context->getObjCGCQualType(T, GCAttr);
Douglas Gregorbdd4ba52009-04-15 22:00:08 +00001319 if (AddressSpace)
Chris Lattner270d29a2009-04-27 21:45:14 +00001320 T = Context->getAddrSpaceQualType(T, AddressSpace);
Douglas Gregorbdd4ba52009-04-15 22:00:08 +00001321 return T;
1322 }
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001323
Douglas Gregorc34897d2009-04-09 22:27:44 +00001324 case pch::TYPE_FIXED_WIDTH_INT: {
1325 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
Chris Lattner270d29a2009-04-27 21:45:14 +00001326 return Context->getFixedWidthIntType(Record[0], Record[1]);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001327 }
1328
1329 case pch::TYPE_COMPLEX: {
1330 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1331 QualType ElemType = GetType(Record[0]);
Chris Lattner270d29a2009-04-27 21:45:14 +00001332 return Context->getComplexType(ElemType);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001333 }
1334
1335 case pch::TYPE_POINTER: {
1336 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1337 QualType PointeeType = GetType(Record[0]);
Chris Lattner270d29a2009-04-27 21:45:14 +00001338 return Context->getPointerType(PointeeType);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001339 }
1340
1341 case pch::TYPE_BLOCK_POINTER: {
1342 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1343 QualType PointeeType = GetType(Record[0]);
Chris Lattner270d29a2009-04-27 21:45:14 +00001344 return Context->getBlockPointerType(PointeeType);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001345 }
1346
1347 case pch::TYPE_LVALUE_REFERENCE: {
1348 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1349 QualType PointeeType = GetType(Record[0]);
Chris Lattner270d29a2009-04-27 21:45:14 +00001350 return Context->getLValueReferenceType(PointeeType);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001351 }
1352
1353 case pch::TYPE_RVALUE_REFERENCE: {
1354 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1355 QualType PointeeType = GetType(Record[0]);
Chris Lattner270d29a2009-04-27 21:45:14 +00001356 return Context->getRValueReferenceType(PointeeType);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001357 }
1358
1359 case pch::TYPE_MEMBER_POINTER: {
1360 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1361 QualType PointeeType = GetType(Record[0]);
1362 QualType ClassType = GetType(Record[1]);
Chris Lattner270d29a2009-04-27 21:45:14 +00001363 return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
Douglas Gregorc34897d2009-04-09 22:27:44 +00001364 }
1365
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001366 case pch::TYPE_CONSTANT_ARRAY: {
1367 QualType ElementType = GetType(Record[0]);
1368 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1369 unsigned IndexTypeQuals = Record[2];
1370 unsigned Idx = 3;
1371 llvm::APInt Size = ReadAPInt(Record, Idx);
Chris Lattner270d29a2009-04-27 21:45:14 +00001372 return Context->getConstantArrayType(ElementType, Size, ASM,IndexTypeQuals);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001373 }
1374
1375 case pch::TYPE_INCOMPLETE_ARRAY: {
1376 QualType ElementType = GetType(Record[0]);
1377 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1378 unsigned IndexTypeQuals = Record[2];
Chris Lattner270d29a2009-04-27 21:45:14 +00001379 return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001380 }
1381
1382 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001383 QualType ElementType = GetType(Record[0]);
1384 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1385 unsigned IndexTypeQuals = Record[2];
Chris Lattner270d29a2009-04-27 21:45:14 +00001386 return Context->getVariableArrayType(ElementType, ReadTypeExpr(),
1387 ASM, IndexTypeQuals);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001388 }
1389
1390 case pch::TYPE_VECTOR: {
1391 if (Record.size() != 2) {
1392 Error("Incorrect encoding of vector type in PCH file");
1393 return QualType();
1394 }
1395
1396 QualType ElementType = GetType(Record[0]);
1397 unsigned NumElements = Record[1];
Chris Lattner270d29a2009-04-27 21:45:14 +00001398 return Context->getVectorType(ElementType, NumElements);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001399 }
1400
1401 case pch::TYPE_EXT_VECTOR: {
1402 if (Record.size() != 2) {
1403 Error("Incorrect encoding of extended vector type in PCH file");
1404 return QualType();
1405 }
1406
1407 QualType ElementType = GetType(Record[0]);
1408 unsigned NumElements = Record[1];
Chris Lattner270d29a2009-04-27 21:45:14 +00001409 return Context->getExtVectorType(ElementType, NumElements);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001410 }
1411
1412 case pch::TYPE_FUNCTION_NO_PROTO: {
1413 if (Record.size() != 1) {
1414 Error("Incorrect encoding of no-proto function type");
1415 return QualType();
1416 }
1417 QualType ResultType = GetType(Record[0]);
Chris Lattner270d29a2009-04-27 21:45:14 +00001418 return Context->getFunctionNoProtoType(ResultType);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001419 }
1420
1421 case pch::TYPE_FUNCTION_PROTO: {
1422 QualType ResultType = GetType(Record[0]);
1423 unsigned Idx = 1;
1424 unsigned NumParams = Record[Idx++];
1425 llvm::SmallVector<QualType, 16> ParamTypes;
1426 for (unsigned I = 0; I != NumParams; ++I)
1427 ParamTypes.push_back(GetType(Record[Idx++]));
1428 bool isVariadic = Record[Idx++];
1429 unsigned Quals = Record[Idx++];
Chris Lattner270d29a2009-04-27 21:45:14 +00001430 return Context->getFunctionType(ResultType, &ParamTypes[0], NumParams,
1431 isVariadic, Quals);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001432 }
1433
1434 case pch::TYPE_TYPEDEF:
1435 assert(Record.size() == 1 && "Incorrect encoding of typedef type");
Chris Lattner270d29a2009-04-27 21:45:14 +00001436 return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001437
1438 case pch::TYPE_TYPEOF_EXPR:
Chris Lattner270d29a2009-04-27 21:45:14 +00001439 return Context->getTypeOfExprType(ReadTypeExpr());
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001440
1441 case pch::TYPE_TYPEOF: {
1442 if (Record.size() != 1) {
1443 Error("Incorrect encoding of typeof(type) in PCH file");
1444 return QualType();
1445 }
1446 QualType UnderlyingType = GetType(Record[0]);
Chris Lattner270d29a2009-04-27 21:45:14 +00001447 return Context->getTypeOfType(UnderlyingType);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001448 }
1449
1450 case pch::TYPE_RECORD:
Douglas Gregor982365e2009-04-13 21:20:57 +00001451 assert(Record.size() == 1 && "Incorrect encoding of record type");
Chris Lattner270d29a2009-04-27 21:45:14 +00001452 return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001453
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001454 case pch::TYPE_ENUM:
1455 assert(Record.size() == 1 && "Incorrect encoding of enum type");
Chris Lattner270d29a2009-04-27 21:45:14 +00001456 return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001457
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001458 case pch::TYPE_OBJC_INTERFACE:
Chris Lattner80f83c62009-04-22 05:57:30 +00001459 assert(Record.size() == 1 && "Incorrect encoding of objc interface type");
Chris Lattner270d29a2009-04-27 21:45:14 +00001460 return Context->getObjCInterfaceType(
Chris Lattner80f83c62009-04-22 05:57:30 +00001461 cast<ObjCInterfaceDecl>(GetDecl(Record[0])));
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001462
Chris Lattnerbab2c0f2009-04-22 06:45:28 +00001463 case pch::TYPE_OBJC_QUALIFIED_INTERFACE: {
1464 unsigned Idx = 0;
1465 ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
1466 unsigned NumProtos = Record[Idx++];
1467 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1468 for (unsigned I = 0; I != NumProtos; ++I)
1469 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Chris Lattner270d29a2009-04-27 21:45:14 +00001470 return Context->getObjCQualifiedInterfaceType(ItfD, &Protos[0], NumProtos);
Chris Lattnerbab2c0f2009-04-22 06:45:28 +00001471 }
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001472
Chris Lattner9b9f2352009-04-22 06:40:03 +00001473 case pch::TYPE_OBJC_QUALIFIED_ID: {
1474 unsigned Idx = 0;
1475 unsigned NumProtos = Record[Idx++];
1476 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1477 for (unsigned I = 0; I != NumProtos; ++I)
1478 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Chris Lattner270d29a2009-04-27 21:45:14 +00001479 return Context->getObjCQualifiedIdType(&Protos[0], NumProtos);
Chris Lattner9b9f2352009-04-22 06:40:03 +00001480 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001481 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001482 // Suppress a GCC warning
1483 return QualType();
1484}
1485
Douglas Gregorc34897d2009-04-09 22:27:44 +00001486
Douglas Gregorac8f2802009-04-10 17:25:41 +00001487QualType PCHReader::GetType(pch::TypeID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001488 unsigned Quals = ID & 0x07;
1489 unsigned Index = ID >> 3;
1490
1491 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
1492 QualType T;
1493 switch ((pch::PredefinedTypeIDs)Index) {
1494 case pch::PREDEF_TYPE_NULL_ID: return QualType();
Chris Lattner270d29a2009-04-27 21:45:14 +00001495 case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
1496 case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001497
1498 case pch::PREDEF_TYPE_CHAR_U_ID:
1499 case pch::PREDEF_TYPE_CHAR_S_ID:
1500 // FIXME: Check that the signedness of CharTy is correct!
Chris Lattner270d29a2009-04-27 21:45:14 +00001501 T = Context->CharTy;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001502 break;
1503
Chris Lattner270d29a2009-04-27 21:45:14 +00001504 case pch::PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break;
1505 case pch::PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break;
1506 case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break;
1507 case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break;
1508 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break;
1509 case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break;
1510 case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break;
1511 case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break;
1512 case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break;
1513 case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break;
1514 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break;
1515 case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break;
1516 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break;
1517 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
1518 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
1519 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001520 }
1521
1522 assert(!T.isNull() && "Unknown predefined type");
1523 return T.getQualifiedType(Quals);
1524 }
1525
1526 Index -= pch::NUM_PREDEF_TYPE_IDS;
Douglas Gregore43f0972009-04-26 03:49:13 +00001527 assert(Index < TypesLoaded.size() && "Type index out-of-range");
Douglas Gregor24a224c2009-04-25 18:35:21 +00001528 if (!TypesLoaded[Index])
1529 TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001530
Douglas Gregor24a224c2009-04-25 18:35:21 +00001531 return QualType(TypesLoaded[Index], Quals);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001532}
1533
Douglas Gregorac8f2802009-04-10 17:25:41 +00001534Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001535 if (ID == 0)
1536 return 0;
1537
Douglas Gregor24a224c2009-04-25 18:35:21 +00001538 if (ID > DeclsLoaded.size()) {
1539 Error("Declaration ID out-of-range for PCH file");
1540 return 0;
1541 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001542
Douglas Gregor24a224c2009-04-25 18:35:21 +00001543 unsigned Index = ID - 1;
1544 if (!DeclsLoaded[Index])
1545 ReadDeclRecord(DeclOffsets[Index], Index);
1546
1547 return DeclsLoaded[Index];
Douglas Gregorc34897d2009-04-09 22:27:44 +00001548}
1549
Chris Lattner77055f62009-04-27 05:46:25 +00001550/// \brief Resolve the offset of a statement into a statement.
1551///
1552/// This operation will read a new statement from the external
1553/// source each time it is called, and is meant to be used via a
1554/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
1555Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
Chris Lattner3ef21962009-04-27 05:58:23 +00001556 // Since we know tha this statement is part of a decl, make sure to use the
1557 // decl cursor to read it.
1558 DeclsCursor.JumpToBit(Offset);
1559 return ReadStmt(DeclsCursor);
Douglas Gregor3b9a7c82009-04-18 00:07:54 +00001560}
1561
Douglas Gregorc34897d2009-04-09 22:27:44 +00001562bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregorac8f2802009-04-10 17:25:41 +00001563 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001564 assert(DC->hasExternalLexicalStorage() &&
1565 "DeclContext has no lexical decls in storage");
1566 uint64_t Offset = DeclContextOffsets[DC].first;
1567 assert(Offset && "DeclContext has no lexical decls in storage");
1568
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001569 // Keep track of where we are in the stream, then jump back there
1570 // after reading this context.
Chris Lattner85e3f642009-04-27 07:35:40 +00001571 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001572
Douglas Gregorc34897d2009-04-09 22:27:44 +00001573 // Load the record containing all of the declarations lexically in
1574 // this context.
Chris Lattner85e3f642009-04-27 07:35:40 +00001575 DeclsCursor.JumpToBit(Offset);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001576 RecordData Record;
Chris Lattner85e3f642009-04-27 07:35:40 +00001577 unsigned Code = DeclsCursor.ReadCode();
1578 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor3c8ff3e2009-04-15 18:43:11 +00001579 (void)RecCode;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001580 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
1581
1582 // Load all of the declaration IDs
1583 Decls.clear();
1584 Decls.insert(Decls.end(), Record.begin(), Record.end());
Douglas Gregoraf136d92009-04-22 22:34:57 +00001585 ++NumLexicalDeclContextsRead;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001586 return false;
1587}
1588
1589bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
Chris Lattner85e3f642009-04-27 07:35:40 +00001590 llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001591 assert(DC->hasExternalVisibleStorage() &&
1592 "DeclContext has no visible decls in storage");
1593 uint64_t Offset = DeclContextOffsets[DC].second;
1594 assert(Offset && "DeclContext has no visible decls in storage");
1595
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001596 // Keep track of where we are in the stream, then jump back there
1597 // after reading this context.
Chris Lattner85e3f642009-04-27 07:35:40 +00001598 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001599
Douglas Gregorc34897d2009-04-09 22:27:44 +00001600 // Load the record containing all of the declarations visible in
1601 // this context.
Chris Lattner85e3f642009-04-27 07:35:40 +00001602 DeclsCursor.JumpToBit(Offset);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001603 RecordData Record;
Chris Lattner85e3f642009-04-27 07:35:40 +00001604 unsigned Code = DeclsCursor.ReadCode();
1605 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor3c8ff3e2009-04-15 18:43:11 +00001606 (void)RecCode;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001607 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
1608 if (Record.size() == 0)
1609 return false;
1610
1611 Decls.clear();
1612
1613 unsigned Idx = 0;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001614 while (Idx < Record.size()) {
1615 Decls.push_back(VisibleDeclaration());
1616 Decls.back().Name = ReadDeclarationName(Record, Idx);
1617
Douglas Gregorc34897d2009-04-09 22:27:44 +00001618 unsigned Size = Record[Idx++];
Chris Lattner85e3f642009-04-27 07:35:40 +00001619 llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001620 LoadedDecls.reserve(Size);
1621 for (unsigned I = 0; I < Size; ++I)
1622 LoadedDecls.push_back(Record[Idx++]);
1623 }
1624
Douglas Gregoraf136d92009-04-22 22:34:57 +00001625 ++NumVisibleDeclContextsRead;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001626 return false;
1627}
1628
Douglas Gregor631f6c62009-04-14 00:24:19 +00001629void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
Douglas Gregor405b6432009-04-22 19:09:20 +00001630 this->Consumer = Consumer;
1631
Douglas Gregor631f6c62009-04-14 00:24:19 +00001632 if (!Consumer)
1633 return;
1634
1635 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
1636 Decl *D = GetDecl(ExternalDefinitions[I]);
1637 DeclGroupRef DG(D);
1638 Consumer->HandleTopLevelDecl(DG);
1639 }
Douglas Gregorf93cfee2009-04-25 00:41:30 +00001640
1641 for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
1642 DeclGroupRef DG(InterestingDecls[I]);
1643 Consumer->HandleTopLevelDecl(DG);
1644 }
Douglas Gregor631f6c62009-04-14 00:24:19 +00001645}
1646
Douglas Gregorc34897d2009-04-09 22:27:44 +00001647void PCHReader::PrintStats() {
1648 std::fprintf(stderr, "*** PCH Statistics:\n");
1649
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001650 unsigned NumTypesLoaded
1651 = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
1652 (Type *)0);
1653 unsigned NumDeclsLoaded
1654 = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
1655 (Decl *)0);
1656 unsigned NumIdentifiersLoaded
1657 = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
1658 IdentifiersLoaded.end(),
1659 (IdentifierInfo *)0);
1660 unsigned NumSelectorsLoaded
1661 = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
1662 SelectorsLoaded.end(),
1663 Selector());
Douglas Gregor9cf47422009-04-13 20:50:16 +00001664
Douglas Gregor6cc5d192009-04-27 18:38:38 +00001665 std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
1666 std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
Douglas Gregor32e231c2009-04-27 06:38:32 +00001667 if (TotalNumSLocEntries)
1668 std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
1669 NumSLocEntriesRead, TotalNumSLocEntries,
1670 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
Douglas Gregor24a224c2009-04-25 18:35:21 +00001671 if (!TypesLoaded.empty())
Douglas Gregor2d711832009-04-25 17:48:32 +00001672 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
Douglas Gregor24a224c2009-04-25 18:35:21 +00001673 NumTypesLoaded, (unsigned)TypesLoaded.size(),
1674 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
1675 if (!DeclsLoaded.empty())
Douglas Gregor2d711832009-04-25 17:48:32 +00001676 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
Douglas Gregor24a224c2009-04-25 18:35:21 +00001677 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
1678 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001679 if (!IdentifiersLoaded.empty())
Douglas Gregor2d711832009-04-25 17:48:32 +00001680 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001681 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
1682 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
Douglas Gregor2d711832009-04-25 17:48:32 +00001683 if (TotalNumSelectors)
1684 std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
1685 NumSelectorsLoaded, TotalNumSelectors,
1686 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
1687 if (TotalNumStatements)
1688 std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
1689 NumStatementsRead, TotalNumStatements,
1690 ((float)NumStatementsRead/TotalNumStatements * 100));
1691 if (TotalNumMacros)
1692 std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
1693 NumMacrosRead, TotalNumMacros,
1694 ((float)NumMacrosRead/TotalNumMacros * 100));
1695 if (TotalLexicalDeclContexts)
1696 std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
1697 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
1698 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
1699 * 100));
1700 if (TotalVisibleDeclContexts)
1701 std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
1702 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
1703 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
1704 * 100));
1705 if (TotalSelectorsInMethodPool) {
1706 std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
1707 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
1708 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
1709 * 100));
1710 std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
1711 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001712 std::fprintf(stderr, "\n");
1713}
1714
Douglas Gregorc713da92009-04-21 22:25:48 +00001715void PCHReader::InitializeSema(Sema &S) {
1716 SemaObj = &S;
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001717 S.ExternalSource = this;
1718
Douglas Gregor2554cf22009-04-22 21:15:06 +00001719 // Makes sure any declarations that were deserialized "too early"
1720 // still get added to the identifier's declaration chains.
1721 for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
1722 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
1723 SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
Douglas Gregorc713da92009-04-21 22:25:48 +00001724 }
Douglas Gregor2554cf22009-04-22 21:15:06 +00001725 PreloadedDecls.clear();
Douglas Gregor77b2cd52009-04-22 22:02:47 +00001726
1727 // If there were any tentative definitions, deserialize them and add
1728 // them to Sema's table of tentative definitions.
1729 for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
1730 VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
1731 SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
1732 }
Douglas Gregor062d9482009-04-22 22:18:58 +00001733
1734 // If there were any locally-scoped external declarations,
1735 // deserialize them and add them to Sema's table of locally-scoped
1736 // external declarations.
1737 for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
1738 NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
1739 SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
1740 }
Douglas Gregorb36b20d2009-04-27 20:06:05 +00001741
1742 // If there were any ext_vector type declarations, deserialize them
1743 // and add them to Sema's vector of such declarations.
1744 for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
1745 SemaObj->ExtVectorDecls.push_back(
1746 cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
1747
1748 // If there were any Objective-C category implementations,
1749 // deserialize them and add them to Sema's vector of such
1750 // definitions.
1751 for (unsigned I = 0, N = ObjCCategoryImpls.size(); I != N; ++I)
1752 SemaObj->ObjCCategoryImpls.push_back(
1753 cast<ObjCCategoryImplDecl>(GetDecl(ObjCCategoryImpls[I])));
Douglas Gregorc713da92009-04-21 22:25:48 +00001754}
1755
1756IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
1757 // Try to find this name within our on-disk hash table
1758 PCHIdentifierLookupTable *IdTable
1759 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1760 std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
1761 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
1762 if (Pos == IdTable->end())
1763 return 0;
1764
1765 // Dereferencing the iterator has the effect of building the
1766 // IdentifierInfo node and populating it with the various
1767 // declarations it needs.
1768 return *Pos;
1769}
1770
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001771std::pair<ObjCMethodList, ObjCMethodList>
1772PCHReader::ReadMethodPool(Selector Sel) {
1773 if (!MethodPoolLookupTable)
1774 return std::pair<ObjCMethodList, ObjCMethodList>();
1775
1776 // Try to find this selector within our on-disk hash table.
1777 PCHMethodPoolLookupTable *PoolTable
1778 = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
1779 PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
Douglas Gregor2d711832009-04-25 17:48:32 +00001780 if (Pos == PoolTable->end()) {
1781 ++NumMethodPoolMisses;
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001782 return std::pair<ObjCMethodList, ObjCMethodList>();;
Douglas Gregor2d711832009-04-25 17:48:32 +00001783 }
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001784
Douglas Gregor2d711832009-04-25 17:48:32 +00001785 ++NumMethodPoolSelectorsRead;
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001786 return *Pos;
1787}
1788
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001789void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
Douglas Gregorc713da92009-04-21 22:25:48 +00001790 assert(ID && "Non-zero identifier ID required");
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001791 assert(ID <= IdentifiersLoaded.size() && "Identifier ID out of range");
1792 IdentifiersLoaded[ID - 1] = II;
Douglas Gregorc713da92009-04-21 22:25:48 +00001793}
1794
Chris Lattner29241862009-04-11 21:15:38 +00001795IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001796 if (ID == 0)
1797 return 0;
Chris Lattner29241862009-04-11 21:15:38 +00001798
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001799 if (!IdentifierTableData || IdentifiersLoaded.empty()) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001800 Error("No identifier table in PCH file");
1801 return 0;
1802 }
Chris Lattner29241862009-04-11 21:15:38 +00001803
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001804 if (!IdentifiersLoaded[ID - 1]) {
1805 uint32_t Offset = IdentifierOffsets[ID - 1];
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001806 const char *Str = IdentifierTableData + Offset;
Douglas Gregor85c4a872009-04-25 21:04:17 +00001807
1808 // If there is an identifier lookup table, but the offset of this
1809 // string is after the identifier table itself, then we know that
1810 // this string is not in the on-disk hash table. Therefore,
1811 // disable lookup into the hash table when looking for this
1812 // identifier.
1813 PCHIdentifierLookupTable *IdTable
1814 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001815 if (!IdTable ||
1816 Offset >= uint32_t(IdTable->getBuckets() - IdTable->getBase())) {
1817 // Turn off lookup into the on-disk hash table. We know that
1818 // this identifier is not there.
1819 if (IdTable)
1820 PP.getIdentifierTable().setExternalIdentifierLookup(0);
Douglas Gregor85c4a872009-04-25 21:04:17 +00001821
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001822 // All of the strings in the PCH file are preceded by a 16-bit
1823 // length. Extract that 16-bit length to avoid having to execute
1824 // strlen().
1825 const char *StrLenPtr = Str - 2;
1826 unsigned StrLen = (((unsigned) StrLenPtr[0])
1827 | (((unsigned) StrLenPtr[1]) << 8)) - 1;
Chris Lattner270d29a2009-04-27 21:45:14 +00001828 IdentifiersLoaded[ID - 1]=&PP.getIdentifierTable().get(Str, Str + StrLen);
Douglas Gregor85c4a872009-04-25 21:04:17 +00001829
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001830 // Turn on lookup into the on-disk hash table, if we have an
1831 // on-disk hash table.
1832 if (IdTable)
1833 PP.getIdentifierTable().setExternalIdentifierLookup(this);
1834 } else {
1835 // The identifier is a key in our on-disk hash table. Since we
1836 // know where the hash table entry starts, just read in this
1837 // (key, value) pair.
1838 PCHIdentifierLookupTrait Trait(const_cast<PCHReader &>(*this));
1839 const unsigned char *Pos = (const unsigned char *)Str - 4;
1840 std::pair<unsigned, unsigned> KeyDataLengths
1841 = Trait.ReadKeyDataLength(Pos);
Douglas Gregor85c4a872009-04-25 21:04:17 +00001842
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001843 PCHIdentifierLookupTrait::internal_key_type InternalKey
1844 = Trait.ReadKey(Pos, KeyDataLengths.first);
1845 Pos = (const unsigned char *)Str + KeyDataLengths.first;
1846 IdentifiersLoaded[ID - 1] = Trait.ReadData(InternalKey, Pos,
1847 KeyDataLengths.second);
1848 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001849 }
Chris Lattner29241862009-04-11 21:15:38 +00001850
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001851 return IdentifiersLoaded[ID - 1];
Douglas Gregorc34897d2009-04-09 22:27:44 +00001852}
1853
Douglas Gregor32e231c2009-04-27 06:38:32 +00001854void PCHReader::ReadSLocEntry(unsigned ID) {
1855 ReadSLocEntryRecord(ID);
1856}
1857
Steve Naroff9e84d782009-04-23 10:39:46 +00001858Selector PCHReader::DecodeSelector(unsigned ID) {
1859 if (ID == 0)
1860 return Selector();
1861
Douglas Gregor2d711832009-04-25 17:48:32 +00001862 if (!MethodPoolLookupTableData) {
Steve Naroff9e84d782009-04-23 10:39:46 +00001863 Error("No selector table in PCH file");
1864 return Selector();
1865 }
Douglas Gregor2d711832009-04-25 17:48:32 +00001866
1867 if (ID > TotalNumSelectors) {
Steve Naroff9e84d782009-04-23 10:39:46 +00001868 Error("Selector ID out of range");
1869 return Selector();
1870 }
Douglas Gregor2d711832009-04-25 17:48:32 +00001871
1872 unsigned Index = ID - 1;
1873 if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
1874 // Load this selector from the selector table.
1875 // FIXME: endianness portability issues with SelectorOffsets table
1876 PCHMethodPoolLookupTrait Trait(*this);
1877 SelectorsLoaded[Index]
1878 = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
1879 }
1880
1881 return SelectorsLoaded[Index];
Steve Naroff9e84d782009-04-23 10:39:46 +00001882}
1883
Douglas Gregorc34897d2009-04-09 22:27:44 +00001884DeclarationName
1885PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
1886 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
1887 switch (Kind) {
1888 case DeclarationName::Identifier:
1889 return DeclarationName(GetIdentifierInfo(Record, Idx));
1890
1891 case DeclarationName::ObjCZeroArgSelector:
1892 case DeclarationName::ObjCOneArgSelector:
1893 case DeclarationName::ObjCMultiArgSelector:
Steve Naroff104956f2009-04-23 15:15:40 +00001894 return DeclarationName(GetSelector(Record, Idx));
Douglas Gregorc34897d2009-04-09 22:27:44 +00001895
1896 case DeclarationName::CXXConstructorName:
Chris Lattner270d29a2009-04-27 21:45:14 +00001897 return Context->DeclarationNames.getCXXConstructorName(
Douglas Gregorc34897d2009-04-09 22:27:44 +00001898 GetType(Record[Idx++]));
1899
1900 case DeclarationName::CXXDestructorName:
Chris Lattner270d29a2009-04-27 21:45:14 +00001901 return Context->DeclarationNames.getCXXDestructorName(
Douglas Gregorc34897d2009-04-09 22:27:44 +00001902 GetType(Record[Idx++]));
1903
1904 case DeclarationName::CXXConversionFunctionName:
Chris Lattner270d29a2009-04-27 21:45:14 +00001905 return Context->DeclarationNames.getCXXConversionFunctionName(
Douglas Gregorc34897d2009-04-09 22:27:44 +00001906 GetType(Record[Idx++]));
1907
1908 case DeclarationName::CXXOperatorName:
Chris Lattner270d29a2009-04-27 21:45:14 +00001909 return Context->DeclarationNames.getCXXOperatorName(
Douglas Gregorc34897d2009-04-09 22:27:44 +00001910 (OverloadedOperatorKind)Record[Idx++]);
1911
1912 case DeclarationName::CXXUsingDirective:
1913 return DeclarationName::getUsingDirectiveName();
1914 }
1915
1916 // Required to silence GCC warning
1917 return DeclarationName();
1918}
Douglas Gregor179cfb12009-04-10 20:39:37 +00001919
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001920/// \brief Read an integral value
1921llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
1922 unsigned BitWidth = Record[Idx++];
1923 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
1924 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
1925 Idx += NumWords;
1926 return Result;
1927}
1928
1929/// \brief Read a signed integral value
1930llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
1931 bool isUnsigned = Record[Idx++];
1932 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
1933}
1934
Douglas Gregore2f37202009-04-14 21:55:33 +00001935/// \brief Read a floating-point value
1936llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
Douglas Gregore2f37202009-04-14 21:55:33 +00001937 return llvm::APFloat(ReadAPInt(Record, Idx));
1938}
1939
Douglas Gregor1c507882009-04-15 21:30:51 +00001940// \brief Read a string
1941std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
1942 unsigned Len = Record[Idx++];
1943 std::string Result(&Record[Idx], &Record[Idx] + Len);
1944 Idx += Len;
1945 return Result;
1946}
1947
Douglas Gregor179cfb12009-04-10 20:39:37 +00001948DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001949 return Diag(SourceLocation(), DiagID);
1950}
1951
1952DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
1953 return PP.getDiagnostics().Report(FullSourceLoc(Loc,
Chris Lattner270d29a2009-04-27 21:45:14 +00001954 PP.getSourceManager()),
Douglas Gregor179cfb12009-04-10 20:39:37 +00001955 DiagID);
1956}
Douglas Gregor9c4782a2009-04-17 00:04:06 +00001957
Douglas Gregorc713da92009-04-21 22:25:48 +00001958/// \brief Retrieve the identifier table associated with the
1959/// preprocessor.
1960IdentifierTable &PCHReader::getIdentifierTable() {
1961 return PP.getIdentifierTable();
1962}
1963
Douglas Gregor9c4782a2009-04-17 00:04:06 +00001964/// \brief Record that the given ID maps to the given switch-case
1965/// statement.
1966void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
1967 assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
1968 SwitchCaseStmts[ID] = SC;
1969}
1970
1971/// \brief Retrieve the switch-case statement with the given ID.
1972SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
1973 assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
1974 return SwitchCaseStmts[ID];
1975}
Douglas Gregor6e411bf2009-04-17 18:18:49 +00001976
1977/// \brief Record that the given label statement has been
1978/// deserialized and has the given ID.
1979void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
1980 assert(LabelStmts.find(ID) == LabelStmts.end() &&
1981 "Deserialized label twice");
1982 LabelStmts[ID] = S;
1983
1984 // If we've already seen any goto statements that point to this
1985 // label, resolve them now.
1986 typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
1987 std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
1988 for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
1989 Goto->second->setLabel(S);
1990 UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
Douglas Gregor95a8fe32009-04-17 18:58:21 +00001991
1992 // If we've already seen any address-label statements that point to
1993 // this label, resolve them now.
1994 typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
1995 std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
1996 = UnresolvedAddrLabelExprs.equal_range(ID);
1997 for (AddrLabelIter AddrLabel = AddrLabels.first;
1998 AddrLabel != AddrLabels.second; ++AddrLabel)
1999 AddrLabel->second->setLabel(S);
2000 UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
Douglas Gregor6e411bf2009-04-17 18:18:49 +00002001}
2002
2003/// \brief Set the label of the given statement to the label
2004/// identified by ID.
2005///
2006/// Depending on the order in which the label and other statements
2007/// referencing that label occur, this operation may complete
2008/// immediately (updating the statement) or it may queue the
2009/// statement to be back-patched later.
2010void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
2011 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2012 if (Label != LabelStmts.end()) {
2013 // We've already seen this label, so set the label of the goto and
2014 // we're done.
2015 S->setLabel(Label->second);
2016 } else {
2017 // We haven't seen this label yet, so add this goto to the set of
2018 // unresolved goto statements.
2019 UnresolvedGotoStmts.insert(std::make_pair(ID, S));
2020 }
2021}
Douglas Gregor95a8fe32009-04-17 18:58:21 +00002022
2023/// \brief Set the label of the given expression to the label
2024/// identified by ID.
2025///
2026/// Depending on the order in which the label and other statements
2027/// referencing that label occur, this operation may complete
2028/// immediately (updating the statement) or it may queue the
2029/// statement to be back-patched later.
2030void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
2031 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2032 if (Label != LabelStmts.end()) {
2033 // We've already seen this label, so set the label of the
2034 // label-address expression and we're done.
2035 S->setLabel(Label->second);
2036 } else {
2037 // We haven't seen this label yet, so add this label-address
2038 // expression to the set of unresolved label-address expressions.
2039 UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
2040 }
2041}