blob: f87252a899235378ebef3f1d3915e1b7e19f196e [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 Lattner09547942009-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 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;
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 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();
273 while (DataLen > 0) {
274 NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
Douglas Gregorc713da92009-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 Gregor2554cf22009-04-22 21:15:06 +0000285 Reader.PreloadedDecls.push_back(D);
Douglas Gregorc713da92009-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 Gregorc34897d2009-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 Gregorb3a04c82009-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 Gregor6cc5d192009-04-27 18:38:38 +0000382//===----------------------------------------------------------------------===//
383// Source Manager Deserialization
384//===----------------------------------------------------------------------===//
385
Douglas Gregor635f97f2009-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 Gregor183ad602009-04-13 17:12:42 +0000394 std::map<int, int> FileIDs;
395 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregor635f97f2009-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 Gregor183ad602009-04-13 17:12:42 +0000400 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
401 Filename.size());
Douglas Gregor635f97f2009-04-13 16:31:14 +0000402 }
403
404 // Parse the line entries
405 std::vector<LineEntry> Entries;
406 while (Idx < Record.size()) {
Douglas Gregor183ad602009-04-13 17:12:42 +0000407 int FID = FileIDs[Record[Idx++]];
Douglas Gregor635f97f2009-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 Gregor6cc5d192009-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 Gregorab1cef72009-04-10 03:52:48 +0000538/// \brief Read the source manager block
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000539PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregorab1cef72009-04-10 03:52:48 +0000540 using namespace SrcMgr;
Douglas Gregor32e231c2009-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 Gregorb3a04c82009-04-10 23:10:45 +0000556 Error("Malformed source manager block record");
557 return Failure;
558 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000559
560 SourceManager &SourceMgr = Context.getSourceManager();
561 RecordData Record;
Douglas Gregorf6e1fb22009-04-26 00:07:37 +0000562 unsigned NumHeaderInfos = 0;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000563 while (true) {
Douglas Gregor32e231c2009-04-27 06:38:32 +0000564 unsigned Code = SLocEntryCursor.ReadCode();
Douglas Gregorab1cef72009-04-10 03:52:48 +0000565 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor32e231c2009-04-27 06:38:32 +0000566 if (SLocEntryCursor.ReadBlockEnd()) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000567 Error("Error at end of Source Manager block");
568 return Failure;
569 }
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000570 return Success;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000571 }
572
573 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
574 // No known subblocks, always skip them.
Douglas Gregor32e231c2009-04-27 06:38:32 +0000575 SLocEntryCursor.ReadSubBlockID();
576 if (SLocEntryCursor.SkipBlock()) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000577 Error("Malformed block record");
578 return Failure;
579 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000580 continue;
581 }
582
583 if (Code == llvm::bitc::DEFINE_ABBREV) {
Douglas Gregor32e231c2009-04-27 06:38:32 +0000584 SLocEntryCursor.ReadAbbrevRecord();
Douglas Gregorab1cef72009-04-10 03:52:48 +0000585 continue;
586 }
587
588 // Read a record.
589 const char *BlobStart;
590 unsigned BlobLen;
591 Record.clear();
Douglas Gregor32e231c2009-04-27 06:38:32 +0000592 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
Douglas Gregorab1cef72009-04-10 03:52:48 +0000593 default: // Default behavior: ignore.
594 break;
595
Chris Lattnere1be6022009-04-14 23:22:57 +0000596 case pch::SM_LINE_TABLE:
Douglas Gregor635f97f2009-04-13 16:31:14 +0000597 if (ParseLineTable(SourceMgr, Record))
598 return Failure;
Chris Lattnere1be6022009-04-14 23:22:57 +0000599 break;
Douglas Gregorf6e1fb22009-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 Gregor32e231c2009-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 Gregorab1cef72009-04-10 03:52:48 +0000616 }
617 }
618}
619
Douglas Gregor32e231c2009-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 Lattner4fc71eb2009-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 Lattner4fc71eb2009-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 Gregore0ad2dd2009-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 Naroffcda68f22009-04-24 20:03:17 +0000731
Douglas Gregore0ad2dd2009-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 Gregore0ad2dd2009-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 Naroffcda68f22009-04-24 20:03:17 +0000820 }
Douglas Gregore0ad2dd2009-04-21 23:56:24 +0000821 }
822}
823
Douglas Gregorc713da92009-04-21 22:25:48 +0000824PCHReader::PCHReadResult
Douglas Gregorf6e1fb22009-04-26 00:07:37 +0000825PCHReader::ReadPCHBlock() {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000826 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
827 Error("Malformed block record");
828 return Failure;
829 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000830
831 // Read all of the records and blocks for the PCH file.
Douglas Gregorac8f2802009-04-10 17:25:41 +0000832 RecordData Record;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000833 while (!Stream.AtEndOfStream()) {
834 unsigned Code = Stream.ReadCode();
835 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000836 if (Stream.ReadBlockEnd()) {
837 Error("Error at end of module block");
838 return Failure;
839 }
Chris Lattner29241862009-04-11 21:15:38 +0000840
Douglas Gregor179cfb12009-04-10 20:39:37 +0000841 return Success;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000842 }
843
844 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
845 switch (Stream.ReadSubBlockID()) {
Douglas Gregorc34897d2009-04-09 22:27:44 +0000846 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
847 default: // Skip unknown content.
Douglas Gregor179cfb12009-04-10 20:39:37 +0000848 if (Stream.SkipBlock()) {
849 Error("Malformed block record");
850 return Failure;
851 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000852 break;
853
Chris Lattner4fc71eb2009-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 Lattner29241862009-04-11 21:15:38 +0000868 case pch::PREPROCESSOR_BLOCK_ID:
Chris Lattner29241862009-04-11 21:15:38 +0000869 if (Stream.SkipBlock()) {
870 Error("Malformed block record");
871 return Failure;
872 }
873 break;
Steve Naroff9e84d782009-04-23 10:39:46 +0000874
Douglas Gregorab1cef72009-04-10 03:52:48 +0000875 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000876 switch (ReadSourceManagerBlock()) {
877 case Success:
878 break;
879
880 case Failure:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000881 Error("Malformed source manager block");
882 return Failure;
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000883
884 case IgnorePCH:
885 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000886 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000887 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000888 }
Douglas Gregorac8f2802009-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 Gregorb5887f32009-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 Gregorac8f2802009-04-10 17:25:41 +0000903 default: // Default behavior: ignore.
904 break;
905
906 case pch::TYPE_OFFSET:
Douglas Gregor24a224c2009-04-25 18:35:21 +0000907 if (!TypesLoaded.empty()) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000908 Error("Duplicate TYPE_OFFSET record in PCH file");
909 return Failure;
910 }
Chris Lattnerea332f32009-04-27 18:24:17 +0000911 TypeOffsets = (const uint32_t *)BlobStart;
Douglas Gregor24a224c2009-04-25 18:35:21 +0000912 TypesLoaded.resize(Record[0]);
Douglas Gregorac8f2802009-04-10 17:25:41 +0000913 break;
914
915 case pch::DECL_OFFSET:
Douglas Gregor24a224c2009-04-25 18:35:21 +0000916 if (!DeclsLoaded.empty()) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000917 Error("Duplicate DECL_OFFSET record in PCH file");
918 return Failure;
919 }
Chris Lattnerea332f32009-04-27 18:24:17 +0000920 DeclOffsets = (const uint32_t *)BlobStart;
Douglas Gregor24a224c2009-04-25 18:35:21 +0000921 DeclsLoaded.resize(Record[0]);
Douglas Gregorac8f2802009-04-10 17:25:41 +0000922 break;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000923
924 case pch::LANGUAGE_OPTIONS:
925 if (ParseLanguageOptions(Record))
926 return IgnorePCH;
927 break;
Douglas Gregorb5887f32009-04-10 21:16:55 +0000928
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000929 case pch::TARGET_TRIPLE: {
Douglas Gregorb5887f32009-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 Gregorc34897d2009-04-09 22:27:44 +0000938 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000939
940 case pch::IDENTIFIER_TABLE:
Douglas Gregorc713da92009-04-21 22:25:48 +0000941 IdentifierTableData = BlobStart;
Douglas Gregorde44c9f2009-04-25 19:10:14 +0000942 if (Record[0]) {
943 IdentifierLookupTable
944 = PCHIdentifierLookupTable::Create(
Douglas Gregorc713da92009-04-21 22:25:48 +0000945 (const unsigned char *)IdentifierTableData + Record[0],
946 (const unsigned char *)IdentifierTableData,
947 PCHIdentifierLookupTrait(*this));
Douglas Gregorde44c9f2009-04-25 19:10:14 +0000948 PP.getIdentifierTable().setExternalIdentifierLookup(this);
949 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000950 break;
951
952 case pch::IDENTIFIER_OFFSET:
Douglas Gregorde44c9f2009-04-25 19:10:14 +0000953 if (!IdentifiersLoaded.empty()) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000954 Error("Duplicate IDENTIFIER_OFFSET record in PCH file");
955 return Failure;
956 }
Douglas Gregorde44c9f2009-04-25 19:10:14 +0000957 IdentifierOffsets = (const uint32_t *)BlobStart;
958 IdentifiersLoaded.resize(Record[0]);
Douglas Gregoreccb51d2009-04-25 23:30:02 +0000959 PP.getHeaderSearchInfo().SetExternalLookup(this);
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000960 break;
Douglas Gregor631f6c62009-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 Gregor456e0952009-04-17 22:13:46 +0000969
Douglas Gregore01ad442009-04-18 05:55:16 +0000970 case pch::SPECIAL_TYPES:
971 SpecialTypes.swap(Record);
972 break;
973
Douglas Gregor456e0952009-04-17 22:13:46 +0000974 case pch::STATISTICS:
975 TotalNumStatements = Record[0];
Douglas Gregore0ad2dd2009-04-21 23:56:24 +0000976 TotalNumMacros = Record[1];
Douglas Gregoraf136d92009-04-22 22:34:57 +0000977 TotalLexicalDeclContexts = Record[2];
978 TotalVisibleDeclContexts = Record[3];
Douglas Gregor456e0952009-04-17 22:13:46 +0000979 break;
Douglas Gregor32e231c2009-04-27 06:38:32 +0000980
Douglas Gregor77b2cd52009-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 Gregor062d9482009-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 Gregorc3221aa2009-04-24 21:10:55 +0000996
Douglas Gregor2d711832009-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 Gregorc3221aa2009-04-24 21:10:55 +00001003 case pch::METHOD_POOL:
Douglas Gregor2d711832009-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 Gregorc3221aa2009-04-24 21:10:55 +00001010 PCHMethodPoolLookupTrait(*this));
Douglas Gregor2d711832009-04-25 17:48:32 +00001011 TotalSelectorsInMethodPool = Record[1];
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001012 break;
Douglas Gregorf6e1fb22009-04-26 00:07:37 +00001013
1014 case pch::PP_COUNTER_VALUE:
1015 if (!Record.empty())
1016 PP.setCounterValue(Record[0]);
1017 break;
Douglas Gregor32e231c2009-04-27 06:38:32 +00001018
1019 case pch::SOURCE_LOCATION_OFFSETS:
1020 SLocOffsets = (const uint64_t *)BlobStart;
1021 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 Gregor6cc5d192009-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 Gregor7a224cf2009-04-11 00:14:32 +00001041 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001042 }
Douglas Gregor179cfb12009-04-10 20:39:37 +00001043 Error("Premature end of bitstream");
1044 return Failure;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001045}
1046
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001047PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor179cfb12009-04-10 20:39:37 +00001048 // Set the PCH file name.
1049 this->FileName = FileName;
1050
Douglas Gregorc34897d2009-04-09 22:27:44 +00001051 // Open the PCH file.
1052 std::string ErrStr;
1053 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001054 if (!Buffer) {
1055 Error(ErrStr.c_str());
1056 return IgnorePCH;
1057 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001058
1059 // Initialize the stream
Chris Lattner587788a2009-04-26 20:59:20 +00001060 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
1061 (const unsigned char *)Buffer->getBufferEnd());
1062 Stream.init(StreamFile);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001063
1064 // Sniff for the signature.
1065 if (Stream.Read(8) != 'C' ||
1066 Stream.Read(8) != 'P' ||
1067 Stream.Read(8) != 'C' ||
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001068 Stream.Read(8) != 'H') {
1069 Error("Not a PCH file");
1070 return IgnorePCH;
1071 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001072
Douglas Gregorc34897d2009-04-09 22:27:44 +00001073 while (!Stream.AtEndOfStream()) {
1074 unsigned Code = Stream.ReadCode();
1075
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001076 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
1077 Error("Invalid record at top-level");
1078 return Failure;
1079 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001080
1081 unsigned BlockID = Stream.ReadSubBlockID();
Douglas Gregorc713da92009-04-21 22:25:48 +00001082
Douglas Gregorc34897d2009-04-09 22:27:44 +00001083 // We only know the PCH subblock ID.
1084 switch (BlockID) {
1085 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001086 if (Stream.ReadBlockInfoBlock()) {
1087 Error("Malformed BlockInfoBlock");
1088 return Failure;
1089 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001090 break;
1091 case pch::PCH_BLOCK_ID:
Douglas Gregorf6e1fb22009-04-26 00:07:37 +00001092 switch (ReadPCHBlock()) {
Douglas Gregor179cfb12009-04-10 20:39:37 +00001093 case Success:
1094 break;
1095
1096 case Failure:
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001097 return Failure;
Douglas Gregor179cfb12009-04-10 20:39:37 +00001098
1099 case IgnorePCH:
Douglas Gregorb5887f32009-04-10 21:16:55 +00001100 // FIXME: We could consider reading through to the end of this
1101 // PCH block, skipping subblocks, to see if there are other
1102 // PCH blocks elsewhere.
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001103 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +00001104 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001105 break;
1106 default:
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001107 if (Stream.SkipBlock()) {
1108 Error("Malformed block record");
1109 return Failure;
1110 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001111 break;
1112 }
1113 }
1114
1115 // Load the translation unit declaration
1116 ReadDeclRecord(DeclOffsets[0], 0);
1117
Douglas Gregorc713da92009-04-21 22:25:48 +00001118 // Initialization of builtins and library builtins occurs before the
1119 // PCH file is read, so there may be some identifiers that were
1120 // loaded into the IdentifierTable before we intercepted the
1121 // creation of identifiers. Iterate through the list of known
1122 // identifiers and determine whether we have to establish
1123 // preprocessor definitions or top-level identifier declaration
1124 // chains for those identifiers.
1125 //
1126 // We copy the IdentifierInfo pointers to a small vector first,
1127 // since de-serializing declarations or macro definitions can add
1128 // new entries into the identifier table, invalidating the
1129 // iterators.
1130 llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
1131 for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
1132 IdEnd = PP.getIdentifierTable().end();
1133 Id != IdEnd; ++Id)
1134 Identifiers.push_back(Id->second);
1135 PCHIdentifierLookupTable *IdTable
1136 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1137 for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
1138 IdentifierInfo *II = Identifiers[I];
1139 // Look in the on-disk hash table for an entry for
1140 PCHIdentifierLookupTrait Info(*this, II);
1141 std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
1142 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
1143 if (Pos == IdTable->end())
1144 continue;
1145
1146 // Dereferencing the iterator has the effect of populating the
1147 // IdentifierInfo node with the various declarations it needs.
1148 (void)*Pos;
1149 }
1150
Douglas Gregore01ad442009-04-18 05:55:16 +00001151 // Load the special types.
1152 Context.setBuiltinVaListType(
1153 GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
Douglas Gregorbb21d4b2009-04-23 22:29:11 +00001154 if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
1155 Context.setObjCIdType(GetType(Id));
1156 if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
1157 Context.setObjCSelType(GetType(Sel));
1158 if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
1159 Context.setObjCProtoType(GetType(Proto));
1160 if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
1161 Context.setObjCClassType(GetType(Class));
1162 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
1163 Context.setCFConstantStringType(GetType(String));
1164 if (unsigned FastEnum
1165 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
1166 Context.setObjCFastEnumerationStateType(GetType(FastEnum));
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001167
Douglas Gregorc713da92009-04-21 22:25:48 +00001168 return Success;
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001169}
1170
Douglas Gregor179cfb12009-04-10 20:39:37 +00001171/// \brief Parse the record that corresponds to a LangOptions data
1172/// structure.
1173///
1174/// This routine compares the language options used to generate the
1175/// PCH file against the language options set for the current
1176/// compilation. For each option, we classify differences between the
1177/// two compiler states as either "benign" or "important". Benign
1178/// differences don't matter, and we accept them without complaint
1179/// (and without modifying the language options). Differences between
1180/// the states for important options cause the PCH file to be
1181/// unusable, so we emit a warning and return true to indicate that
1182/// there was an error.
1183///
1184/// \returns true if the PCH file is unacceptable, false otherwise.
1185bool PCHReader::ParseLanguageOptions(
1186 const llvm::SmallVectorImpl<uint64_t> &Record) {
1187 const LangOptions &LangOpts = Context.getLangOptions();
1188#define PARSE_LANGOPT_BENIGN(Option) ++Idx
1189#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
1190 if (Record[Idx] != LangOpts.Option) { \
1191 Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
1192 Diag(diag::note_ignoring_pch) << FileName; \
1193 return true; \
1194 } \
1195 ++Idx
1196
1197 unsigned Idx = 0;
1198 PARSE_LANGOPT_BENIGN(Trigraphs);
1199 PARSE_LANGOPT_BENIGN(BCPLComment);
1200 PARSE_LANGOPT_BENIGN(DollarIdents);
1201 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
1202 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
1203 PARSE_LANGOPT_BENIGN(ImplicitInt);
1204 PARSE_LANGOPT_BENIGN(Digraphs);
1205 PARSE_LANGOPT_BENIGN(HexFloats);
1206 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
1207 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
1208 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
1209 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
1210 PARSE_LANGOPT_IMPORTANT(NoExtensions, diag::warn_pch_extensions);
1211 PARSE_LANGOPT_BENIGN(CXXOperatorName);
1212 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
1213 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
1214 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
1215 PARSE_LANGOPT_BENIGN(PascalStrings);
1216 PARSE_LANGOPT_BENIGN(Boolean);
1217 PARSE_LANGOPT_BENIGN(WritableStrings);
1218 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
1219 diag::warn_pch_lax_vector_conversions);
1220 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
1221 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
1222 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
1223 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
1224 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
1225 diag::warn_pch_thread_safe_statics);
1226 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
1227 PARSE_LANGOPT_BENIGN(EmitAllDecls);
1228 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
1229 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
1230 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
1231 diag::warn_pch_heinous_extensions);
1232 // FIXME: Most of the options below are benign if the macro wasn't
1233 // used. Unfortunately, this means that a PCH compiled without
1234 // optimization can't be used with optimization turned on, even
1235 // though the only thing that changes is whether __OPTIMIZE__ was
1236 // defined... but if __OPTIMIZE__ never showed up in the header, it
1237 // doesn't matter. We could consider making this some special kind
1238 // of check.
1239 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
1240 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
1241 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
1242 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
1243 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
1244 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
1245 if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
1246 Diag(diag::warn_pch_gc_mode)
1247 << (unsigned)Record[Idx] << LangOpts.getGCMode();
1248 Diag(diag::note_ignoring_pch) << FileName;
1249 return true;
1250 }
1251 ++Idx;
1252 PARSE_LANGOPT_BENIGN(getVisibilityMode());
1253 PARSE_LANGOPT_BENIGN(InstantiationDepth);
1254#undef PARSE_LANGOPT_IRRELEVANT
1255#undef PARSE_LANGOPT_BENIGN
1256
1257 return false;
1258}
1259
Douglas Gregorc34897d2009-04-09 22:27:44 +00001260/// \brief Read and return the type at the given offset.
1261///
1262/// This routine actually reads the record corresponding to the type
1263/// at the given offset in the bitstream. It is a helper routine for
1264/// GetType, which deals with reading type IDs.
1265QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001266 // Keep track of where we are in the stream, then jump back there
1267 // after reading this type.
1268 SavedStreamPosition SavedPosition(Stream);
1269
Douglas Gregorc34897d2009-04-09 22:27:44 +00001270 Stream.JumpToBit(Offset);
1271 RecordData Record;
1272 unsigned Code = Stream.ReadCode();
1273 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
Douglas Gregorbdd4ba52009-04-15 22:00:08 +00001274 case pch::TYPE_EXT_QUAL: {
1275 assert(Record.size() == 3 &&
1276 "Incorrect encoding of extended qualifier type");
1277 QualType Base = GetType(Record[0]);
1278 QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1];
1279 unsigned AddressSpace = Record[2];
1280
1281 QualType T = Base;
1282 if (GCAttr != QualType::GCNone)
1283 T = Context.getObjCGCQualType(T, GCAttr);
1284 if (AddressSpace)
1285 T = Context.getAddrSpaceQualType(T, AddressSpace);
1286 return T;
1287 }
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001288
Douglas Gregorc34897d2009-04-09 22:27:44 +00001289 case pch::TYPE_FIXED_WIDTH_INT: {
1290 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
1291 return Context.getFixedWidthIntType(Record[0], Record[1]);
1292 }
1293
1294 case pch::TYPE_COMPLEX: {
1295 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1296 QualType ElemType = GetType(Record[0]);
1297 return Context.getComplexType(ElemType);
1298 }
1299
1300 case pch::TYPE_POINTER: {
1301 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1302 QualType PointeeType = GetType(Record[0]);
1303 return Context.getPointerType(PointeeType);
1304 }
1305
1306 case pch::TYPE_BLOCK_POINTER: {
1307 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1308 QualType PointeeType = GetType(Record[0]);
1309 return Context.getBlockPointerType(PointeeType);
1310 }
1311
1312 case pch::TYPE_LVALUE_REFERENCE: {
1313 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1314 QualType PointeeType = GetType(Record[0]);
1315 return Context.getLValueReferenceType(PointeeType);
1316 }
1317
1318 case pch::TYPE_RVALUE_REFERENCE: {
1319 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1320 QualType PointeeType = GetType(Record[0]);
1321 return Context.getRValueReferenceType(PointeeType);
1322 }
1323
1324 case pch::TYPE_MEMBER_POINTER: {
1325 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1326 QualType PointeeType = GetType(Record[0]);
1327 QualType ClassType = GetType(Record[1]);
1328 return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
1329 }
1330
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001331 case pch::TYPE_CONSTANT_ARRAY: {
1332 QualType ElementType = GetType(Record[0]);
1333 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1334 unsigned IndexTypeQuals = Record[2];
1335 unsigned Idx = 3;
1336 llvm::APInt Size = ReadAPInt(Record, Idx);
1337 return Context.getConstantArrayType(ElementType, Size, ASM, IndexTypeQuals);
1338 }
1339
1340 case pch::TYPE_INCOMPLETE_ARRAY: {
1341 QualType ElementType = GetType(Record[0]);
1342 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1343 unsigned IndexTypeQuals = Record[2];
1344 return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
1345 }
1346
1347 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001348 QualType ElementType = GetType(Record[0]);
1349 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1350 unsigned IndexTypeQuals = Record[2];
Chris Lattner3ef21962009-04-27 05:58:23 +00001351 return Context.getVariableArrayType(ElementType, ReadTypeExpr(),
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001352 ASM, IndexTypeQuals);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001353 }
1354
1355 case pch::TYPE_VECTOR: {
1356 if (Record.size() != 2) {
1357 Error("Incorrect encoding of vector type in PCH file");
1358 return QualType();
1359 }
1360
1361 QualType ElementType = GetType(Record[0]);
1362 unsigned NumElements = Record[1];
1363 return Context.getVectorType(ElementType, NumElements);
1364 }
1365
1366 case pch::TYPE_EXT_VECTOR: {
1367 if (Record.size() != 2) {
1368 Error("Incorrect encoding of extended vector type in PCH file");
1369 return QualType();
1370 }
1371
1372 QualType ElementType = GetType(Record[0]);
1373 unsigned NumElements = Record[1];
1374 return Context.getExtVectorType(ElementType, NumElements);
1375 }
1376
1377 case pch::TYPE_FUNCTION_NO_PROTO: {
1378 if (Record.size() != 1) {
1379 Error("Incorrect encoding of no-proto function type");
1380 return QualType();
1381 }
1382 QualType ResultType = GetType(Record[0]);
1383 return Context.getFunctionNoProtoType(ResultType);
1384 }
1385
1386 case pch::TYPE_FUNCTION_PROTO: {
1387 QualType ResultType = GetType(Record[0]);
1388 unsigned Idx = 1;
1389 unsigned NumParams = Record[Idx++];
1390 llvm::SmallVector<QualType, 16> ParamTypes;
1391 for (unsigned I = 0; I != NumParams; ++I)
1392 ParamTypes.push_back(GetType(Record[Idx++]));
1393 bool isVariadic = Record[Idx++];
1394 unsigned Quals = Record[Idx++];
1395 return Context.getFunctionType(ResultType, &ParamTypes[0], NumParams,
1396 isVariadic, Quals);
1397 }
1398
1399 case pch::TYPE_TYPEDEF:
1400 assert(Record.size() == 1 && "Incorrect encoding of typedef type");
1401 return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
1402
1403 case pch::TYPE_TYPEOF_EXPR:
Chris Lattner3ef21962009-04-27 05:58:23 +00001404 return Context.getTypeOfExprType(ReadTypeExpr());
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001405
1406 case pch::TYPE_TYPEOF: {
1407 if (Record.size() != 1) {
1408 Error("Incorrect encoding of typeof(type) in PCH file");
1409 return QualType();
1410 }
1411 QualType UnderlyingType = GetType(Record[0]);
1412 return Context.getTypeOfType(UnderlyingType);
1413 }
1414
1415 case pch::TYPE_RECORD:
Douglas Gregor982365e2009-04-13 21:20:57 +00001416 assert(Record.size() == 1 && "Incorrect encoding of record type");
1417 return Context.getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001418
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001419 case pch::TYPE_ENUM:
1420 assert(Record.size() == 1 && "Incorrect encoding of enum type");
1421 return Context.getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
1422
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001423 case pch::TYPE_OBJC_INTERFACE:
Chris Lattner80f83c62009-04-22 05:57:30 +00001424 assert(Record.size() == 1 && "Incorrect encoding of objc interface type");
1425 return Context.getObjCInterfaceType(
1426 cast<ObjCInterfaceDecl>(GetDecl(Record[0])));
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001427
Chris Lattnerbab2c0f2009-04-22 06:45:28 +00001428 case pch::TYPE_OBJC_QUALIFIED_INTERFACE: {
1429 unsigned Idx = 0;
1430 ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
1431 unsigned NumProtos = Record[Idx++];
1432 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1433 for (unsigned I = 0; I != NumProtos; ++I)
1434 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
1435 return Context.getObjCQualifiedInterfaceType(ItfD, &Protos[0], NumProtos);
1436 }
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001437
Chris Lattner9b9f2352009-04-22 06:40:03 +00001438 case pch::TYPE_OBJC_QUALIFIED_ID: {
1439 unsigned Idx = 0;
1440 unsigned NumProtos = Record[Idx++];
1441 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1442 for (unsigned I = 0; I != NumProtos; ++I)
1443 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
1444 return Context.getObjCQualifiedIdType(&Protos[0], NumProtos);
1445 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001446 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001447 // Suppress a GCC warning
1448 return QualType();
1449}
1450
Douglas Gregorc34897d2009-04-09 22:27:44 +00001451
Douglas Gregorac8f2802009-04-10 17:25:41 +00001452QualType PCHReader::GetType(pch::TypeID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001453 unsigned Quals = ID & 0x07;
1454 unsigned Index = ID >> 3;
1455
1456 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
1457 QualType T;
1458 switch ((pch::PredefinedTypeIDs)Index) {
1459 case pch::PREDEF_TYPE_NULL_ID: return QualType();
1460 case pch::PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
1461 case pch::PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
1462
1463 case pch::PREDEF_TYPE_CHAR_U_ID:
1464 case pch::PREDEF_TYPE_CHAR_S_ID:
1465 // FIXME: Check that the signedness of CharTy is correct!
1466 T = Context.CharTy;
1467 break;
1468
1469 case pch::PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
1470 case pch::PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
1471 case pch::PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
1472 case pch::PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
1473 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
1474 case pch::PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
1475 case pch::PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
1476 case pch::PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
1477 case pch::PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
1478 case pch::PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
1479 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
1480 case pch::PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
1481 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
1482 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
1483 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
1484 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
1485 }
1486
1487 assert(!T.isNull() && "Unknown predefined type");
1488 return T.getQualifiedType(Quals);
1489 }
1490
1491 Index -= pch::NUM_PREDEF_TYPE_IDS;
Douglas Gregore43f0972009-04-26 03:49:13 +00001492 assert(Index < TypesLoaded.size() && "Type index out-of-range");
Douglas Gregor24a224c2009-04-25 18:35:21 +00001493 if (!TypesLoaded[Index])
1494 TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001495
Douglas Gregor24a224c2009-04-25 18:35:21 +00001496 return QualType(TypesLoaded[Index], Quals);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001497}
1498
Douglas Gregorac8f2802009-04-10 17:25:41 +00001499Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001500 if (ID == 0)
1501 return 0;
1502
Douglas Gregor24a224c2009-04-25 18:35:21 +00001503 if (ID > DeclsLoaded.size()) {
1504 Error("Declaration ID out-of-range for PCH file");
1505 return 0;
1506 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001507
Douglas Gregor24a224c2009-04-25 18:35:21 +00001508 unsigned Index = ID - 1;
1509 if (!DeclsLoaded[Index])
1510 ReadDeclRecord(DeclOffsets[Index], Index);
1511
1512 return DeclsLoaded[Index];
Douglas Gregorc34897d2009-04-09 22:27:44 +00001513}
1514
Chris Lattner77055f62009-04-27 05:46:25 +00001515/// \brief Resolve the offset of a statement into a statement.
1516///
1517/// This operation will read a new statement from the external
1518/// source each time it is called, and is meant to be used via a
1519/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
1520Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
Chris Lattner3ef21962009-04-27 05:58:23 +00001521 // Since we know tha this statement is part of a decl, make sure to use the
1522 // decl cursor to read it.
1523 DeclsCursor.JumpToBit(Offset);
1524 return ReadStmt(DeclsCursor);
Douglas Gregor3b9a7c82009-04-18 00:07:54 +00001525}
1526
Douglas Gregorc34897d2009-04-09 22:27:44 +00001527bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregorac8f2802009-04-10 17:25:41 +00001528 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001529 assert(DC->hasExternalLexicalStorage() &&
1530 "DeclContext has no lexical decls in storage");
1531 uint64_t Offset = DeclContextOffsets[DC].first;
1532 assert(Offset && "DeclContext has no lexical decls in storage");
1533
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001534 // Keep track of where we are in the stream, then jump back there
1535 // after reading this context.
Chris Lattner85e3f642009-04-27 07:35:40 +00001536 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001537
Douglas Gregorc34897d2009-04-09 22:27:44 +00001538 // Load the record containing all of the declarations lexically in
1539 // this context.
Chris Lattner85e3f642009-04-27 07:35:40 +00001540 DeclsCursor.JumpToBit(Offset);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001541 RecordData Record;
Chris Lattner85e3f642009-04-27 07:35:40 +00001542 unsigned Code = DeclsCursor.ReadCode();
1543 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor3c8ff3e2009-04-15 18:43:11 +00001544 (void)RecCode;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001545 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
1546
1547 // Load all of the declaration IDs
1548 Decls.clear();
1549 Decls.insert(Decls.end(), Record.begin(), Record.end());
Douglas Gregoraf136d92009-04-22 22:34:57 +00001550 ++NumLexicalDeclContextsRead;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001551 return false;
1552}
1553
1554bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
Chris Lattner85e3f642009-04-27 07:35:40 +00001555 llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001556 assert(DC->hasExternalVisibleStorage() &&
1557 "DeclContext has no visible decls in storage");
1558 uint64_t Offset = DeclContextOffsets[DC].second;
1559 assert(Offset && "DeclContext has no visible decls in storage");
1560
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001561 // Keep track of where we are in the stream, then jump back there
1562 // after reading this context.
Chris Lattner85e3f642009-04-27 07:35:40 +00001563 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001564
Douglas Gregorc34897d2009-04-09 22:27:44 +00001565 // Load the record containing all of the declarations visible in
1566 // this context.
Chris Lattner85e3f642009-04-27 07:35:40 +00001567 DeclsCursor.JumpToBit(Offset);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001568 RecordData Record;
Chris Lattner85e3f642009-04-27 07:35:40 +00001569 unsigned Code = DeclsCursor.ReadCode();
1570 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor3c8ff3e2009-04-15 18:43:11 +00001571 (void)RecCode;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001572 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
1573 if (Record.size() == 0)
1574 return false;
1575
1576 Decls.clear();
1577
1578 unsigned Idx = 0;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001579 while (Idx < Record.size()) {
1580 Decls.push_back(VisibleDeclaration());
1581 Decls.back().Name = ReadDeclarationName(Record, Idx);
1582
Douglas Gregorc34897d2009-04-09 22:27:44 +00001583 unsigned Size = Record[Idx++];
Chris Lattner85e3f642009-04-27 07:35:40 +00001584 llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001585 LoadedDecls.reserve(Size);
1586 for (unsigned I = 0; I < Size; ++I)
1587 LoadedDecls.push_back(Record[Idx++]);
1588 }
1589
Douglas Gregoraf136d92009-04-22 22:34:57 +00001590 ++NumVisibleDeclContextsRead;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001591 return false;
1592}
1593
Douglas Gregor631f6c62009-04-14 00:24:19 +00001594void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
Douglas Gregor405b6432009-04-22 19:09:20 +00001595 this->Consumer = Consumer;
1596
Douglas Gregor631f6c62009-04-14 00:24:19 +00001597 if (!Consumer)
1598 return;
1599
1600 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
1601 Decl *D = GetDecl(ExternalDefinitions[I]);
1602 DeclGroupRef DG(D);
1603 Consumer->HandleTopLevelDecl(DG);
1604 }
Douglas Gregorf93cfee2009-04-25 00:41:30 +00001605
1606 for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
1607 DeclGroupRef DG(InterestingDecls[I]);
1608 Consumer->HandleTopLevelDecl(DG);
1609 }
Douglas Gregor631f6c62009-04-14 00:24:19 +00001610}
1611
Douglas Gregorc34897d2009-04-09 22:27:44 +00001612void PCHReader::PrintStats() {
1613 std::fprintf(stderr, "*** PCH Statistics:\n");
1614
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001615 unsigned NumTypesLoaded
1616 = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
1617 (Type *)0);
1618 unsigned NumDeclsLoaded
1619 = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
1620 (Decl *)0);
1621 unsigned NumIdentifiersLoaded
1622 = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
1623 IdentifiersLoaded.end(),
1624 (IdentifierInfo *)0);
1625 unsigned NumSelectorsLoaded
1626 = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
1627 SelectorsLoaded.end(),
1628 Selector());
Douglas Gregor9cf47422009-04-13 20:50:16 +00001629
Douglas Gregor6cc5d192009-04-27 18:38:38 +00001630 std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
1631 std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
Douglas Gregor32e231c2009-04-27 06:38:32 +00001632 if (TotalNumSLocEntries)
1633 std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
1634 NumSLocEntriesRead, TotalNumSLocEntries,
1635 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
Douglas Gregor24a224c2009-04-25 18:35:21 +00001636 if (!TypesLoaded.empty())
Douglas Gregor2d711832009-04-25 17:48:32 +00001637 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
Douglas Gregor24a224c2009-04-25 18:35:21 +00001638 NumTypesLoaded, (unsigned)TypesLoaded.size(),
1639 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
1640 if (!DeclsLoaded.empty())
Douglas Gregor2d711832009-04-25 17:48:32 +00001641 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
Douglas Gregor24a224c2009-04-25 18:35:21 +00001642 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
1643 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001644 if (!IdentifiersLoaded.empty())
Douglas Gregor2d711832009-04-25 17:48:32 +00001645 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001646 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
1647 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
Douglas Gregor2d711832009-04-25 17:48:32 +00001648 if (TotalNumSelectors)
1649 std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
1650 NumSelectorsLoaded, TotalNumSelectors,
1651 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
1652 if (TotalNumStatements)
1653 std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
1654 NumStatementsRead, TotalNumStatements,
1655 ((float)NumStatementsRead/TotalNumStatements * 100));
1656 if (TotalNumMacros)
1657 std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
1658 NumMacrosRead, TotalNumMacros,
1659 ((float)NumMacrosRead/TotalNumMacros * 100));
1660 if (TotalLexicalDeclContexts)
1661 std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
1662 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
1663 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
1664 * 100));
1665 if (TotalVisibleDeclContexts)
1666 std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
1667 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
1668 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
1669 * 100));
1670 if (TotalSelectorsInMethodPool) {
1671 std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
1672 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
1673 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
1674 * 100));
1675 std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
1676 }
Douglas Gregorc34897d2009-04-09 22:27:44 +00001677 std::fprintf(stderr, "\n");
1678}
1679
Douglas Gregorc713da92009-04-21 22:25:48 +00001680void PCHReader::InitializeSema(Sema &S) {
1681 SemaObj = &S;
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001682 S.ExternalSource = this;
1683
Douglas Gregor2554cf22009-04-22 21:15:06 +00001684 // Makes sure any declarations that were deserialized "too early"
1685 // still get added to the identifier's declaration chains.
1686 for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
1687 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
1688 SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
Douglas Gregorc713da92009-04-21 22:25:48 +00001689 }
Douglas Gregor2554cf22009-04-22 21:15:06 +00001690 PreloadedDecls.clear();
Douglas Gregor77b2cd52009-04-22 22:02:47 +00001691
1692 // If there were any tentative definitions, deserialize them and add
1693 // them to Sema's table of tentative definitions.
1694 for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
1695 VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
1696 SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
1697 }
Douglas Gregor062d9482009-04-22 22:18:58 +00001698
1699 // If there were any locally-scoped external declarations,
1700 // deserialize them and add them to Sema's table of locally-scoped
1701 // external declarations.
1702 for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
1703 NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
1704 SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
1705 }
Douglas Gregorc713da92009-04-21 22:25:48 +00001706}
1707
1708IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
1709 // Try to find this name within our on-disk hash table
1710 PCHIdentifierLookupTable *IdTable
1711 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1712 std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
1713 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
1714 if (Pos == IdTable->end())
1715 return 0;
1716
1717 // Dereferencing the iterator has the effect of building the
1718 // IdentifierInfo node and populating it with the various
1719 // declarations it needs.
1720 return *Pos;
1721}
1722
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001723std::pair<ObjCMethodList, ObjCMethodList>
1724PCHReader::ReadMethodPool(Selector Sel) {
1725 if (!MethodPoolLookupTable)
1726 return std::pair<ObjCMethodList, ObjCMethodList>();
1727
1728 // Try to find this selector within our on-disk hash table.
1729 PCHMethodPoolLookupTable *PoolTable
1730 = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
1731 PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
Douglas Gregor2d711832009-04-25 17:48:32 +00001732 if (Pos == PoolTable->end()) {
1733 ++NumMethodPoolMisses;
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001734 return std::pair<ObjCMethodList, ObjCMethodList>();;
Douglas Gregor2d711832009-04-25 17:48:32 +00001735 }
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001736
Douglas Gregor2d711832009-04-25 17:48:32 +00001737 ++NumMethodPoolSelectorsRead;
Douglas Gregorc3221aa2009-04-24 21:10:55 +00001738 return *Pos;
1739}
1740
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001741void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
Douglas Gregorc713da92009-04-21 22:25:48 +00001742 assert(ID && "Non-zero identifier ID required");
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001743 assert(ID <= IdentifiersLoaded.size() && "Identifier ID out of range");
1744 IdentifiersLoaded[ID - 1] = II;
Douglas Gregorc713da92009-04-21 22:25:48 +00001745}
1746
Chris Lattner29241862009-04-11 21:15:38 +00001747IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001748 if (ID == 0)
1749 return 0;
Chris Lattner29241862009-04-11 21:15:38 +00001750
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001751 if (!IdentifierTableData || IdentifiersLoaded.empty()) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001752 Error("No identifier table in PCH file");
1753 return 0;
1754 }
Chris Lattner29241862009-04-11 21:15:38 +00001755
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001756 if (!IdentifiersLoaded[ID - 1]) {
1757 uint32_t Offset = IdentifierOffsets[ID - 1];
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001758 const char *Str = IdentifierTableData + Offset;
Douglas Gregor85c4a872009-04-25 21:04:17 +00001759
1760 // If there is an identifier lookup table, but the offset of this
1761 // string is after the identifier table itself, then we know that
1762 // this string is not in the on-disk hash table. Therefore,
1763 // disable lookup into the hash table when looking for this
1764 // identifier.
1765 PCHIdentifierLookupTable *IdTable
1766 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001767 if (!IdTable ||
1768 Offset >= uint32_t(IdTable->getBuckets() - IdTable->getBase())) {
1769 // Turn off lookup into the on-disk hash table. We know that
1770 // this identifier is not there.
1771 if (IdTable)
1772 PP.getIdentifierTable().setExternalIdentifierLookup(0);
Douglas Gregor85c4a872009-04-25 21:04:17 +00001773
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001774 // All of the strings in the PCH file are preceded by a 16-bit
1775 // length. Extract that 16-bit length to avoid having to execute
1776 // strlen().
1777 const char *StrLenPtr = Str - 2;
1778 unsigned StrLen = (((unsigned) StrLenPtr[0])
1779 | (((unsigned) StrLenPtr[1]) << 8)) - 1;
1780 IdentifiersLoaded[ID - 1] = &Context.Idents.get(Str, Str + StrLen);
Douglas Gregor85c4a872009-04-25 21:04:17 +00001781
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001782 // Turn on lookup into the on-disk hash table, if we have an
1783 // on-disk hash table.
1784 if (IdTable)
1785 PP.getIdentifierTable().setExternalIdentifierLookup(this);
1786 } else {
1787 // The identifier is a key in our on-disk hash table. Since we
1788 // know where the hash table entry starts, just read in this
1789 // (key, value) pair.
1790 PCHIdentifierLookupTrait Trait(const_cast<PCHReader &>(*this));
1791 const unsigned char *Pos = (const unsigned char *)Str - 4;
1792 std::pair<unsigned, unsigned> KeyDataLengths
1793 = Trait.ReadKeyDataLength(Pos);
Douglas Gregor85c4a872009-04-25 21:04:17 +00001794
Douglas Gregor4d7a6e42009-04-25 21:21:38 +00001795 PCHIdentifierLookupTrait::internal_key_type InternalKey
1796 = Trait.ReadKey(Pos, KeyDataLengths.first);
1797 Pos = (const unsigned char *)Str + KeyDataLengths.first;
1798 IdentifiersLoaded[ID - 1] = Trait.ReadData(InternalKey, Pos,
1799 KeyDataLengths.second);
1800 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001801 }
Chris Lattner29241862009-04-11 21:15:38 +00001802
Douglas Gregorde44c9f2009-04-25 19:10:14 +00001803 return IdentifiersLoaded[ID - 1];
Douglas Gregorc34897d2009-04-09 22:27:44 +00001804}
1805
Douglas Gregor32e231c2009-04-27 06:38:32 +00001806void PCHReader::ReadSLocEntry(unsigned ID) {
1807 ReadSLocEntryRecord(ID);
1808}
1809
Steve Naroff9e84d782009-04-23 10:39:46 +00001810Selector PCHReader::DecodeSelector(unsigned ID) {
1811 if (ID == 0)
1812 return Selector();
1813
Douglas Gregor2d711832009-04-25 17:48:32 +00001814 if (!MethodPoolLookupTableData) {
Steve Naroff9e84d782009-04-23 10:39:46 +00001815 Error("No selector table in PCH file");
1816 return Selector();
1817 }
Douglas Gregor2d711832009-04-25 17:48:32 +00001818
1819 if (ID > TotalNumSelectors) {
Steve Naroff9e84d782009-04-23 10:39:46 +00001820 Error("Selector ID out of range");
1821 return Selector();
1822 }
Douglas Gregor2d711832009-04-25 17:48:32 +00001823
1824 unsigned Index = ID - 1;
1825 if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
1826 // Load this selector from the selector table.
1827 // FIXME: endianness portability issues with SelectorOffsets table
1828 PCHMethodPoolLookupTrait Trait(*this);
1829 SelectorsLoaded[Index]
1830 = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
1831 }
1832
1833 return SelectorsLoaded[Index];
Steve Naroff9e84d782009-04-23 10:39:46 +00001834}
1835
Douglas Gregorc34897d2009-04-09 22:27:44 +00001836DeclarationName
1837PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
1838 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
1839 switch (Kind) {
1840 case DeclarationName::Identifier:
1841 return DeclarationName(GetIdentifierInfo(Record, Idx));
1842
1843 case DeclarationName::ObjCZeroArgSelector:
1844 case DeclarationName::ObjCOneArgSelector:
1845 case DeclarationName::ObjCMultiArgSelector:
Steve Naroff104956f2009-04-23 15:15:40 +00001846 return DeclarationName(GetSelector(Record, Idx));
Douglas Gregorc34897d2009-04-09 22:27:44 +00001847
1848 case DeclarationName::CXXConstructorName:
1849 return Context.DeclarationNames.getCXXConstructorName(
1850 GetType(Record[Idx++]));
1851
1852 case DeclarationName::CXXDestructorName:
1853 return Context.DeclarationNames.getCXXDestructorName(
1854 GetType(Record[Idx++]));
1855
1856 case DeclarationName::CXXConversionFunctionName:
1857 return Context.DeclarationNames.getCXXConversionFunctionName(
1858 GetType(Record[Idx++]));
1859
1860 case DeclarationName::CXXOperatorName:
1861 return Context.DeclarationNames.getCXXOperatorName(
1862 (OverloadedOperatorKind)Record[Idx++]);
1863
1864 case DeclarationName::CXXUsingDirective:
1865 return DeclarationName::getUsingDirectiveName();
1866 }
1867
1868 // Required to silence GCC warning
1869 return DeclarationName();
1870}
Douglas Gregor179cfb12009-04-10 20:39:37 +00001871
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001872/// \brief Read an integral value
1873llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
1874 unsigned BitWidth = Record[Idx++];
1875 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
1876 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
1877 Idx += NumWords;
1878 return Result;
1879}
1880
1881/// \brief Read a signed integral value
1882llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
1883 bool isUnsigned = Record[Idx++];
1884 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
1885}
1886
Douglas Gregore2f37202009-04-14 21:55:33 +00001887/// \brief Read a floating-point value
1888llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
Douglas Gregore2f37202009-04-14 21:55:33 +00001889 return llvm::APFloat(ReadAPInt(Record, Idx));
1890}
1891
Douglas Gregor1c507882009-04-15 21:30:51 +00001892// \brief Read a string
1893std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
1894 unsigned Len = Record[Idx++];
1895 std::string Result(&Record[Idx], &Record[Idx] + Len);
1896 Idx += Len;
1897 return Result;
1898}
1899
Douglas Gregor179cfb12009-04-10 20:39:37 +00001900DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001901 return Diag(SourceLocation(), DiagID);
1902}
1903
1904DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
1905 return PP.getDiagnostics().Report(FullSourceLoc(Loc,
Douglas Gregor179cfb12009-04-10 20:39:37 +00001906 Context.getSourceManager()),
1907 DiagID);
1908}
Douglas Gregor9c4782a2009-04-17 00:04:06 +00001909
Douglas Gregorc713da92009-04-21 22:25:48 +00001910/// \brief Retrieve the identifier table associated with the
1911/// preprocessor.
1912IdentifierTable &PCHReader::getIdentifierTable() {
1913 return PP.getIdentifierTable();
1914}
1915
Douglas Gregor9c4782a2009-04-17 00:04:06 +00001916/// \brief Record that the given ID maps to the given switch-case
1917/// statement.
1918void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
1919 assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
1920 SwitchCaseStmts[ID] = SC;
1921}
1922
1923/// \brief Retrieve the switch-case statement with the given ID.
1924SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
1925 assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
1926 return SwitchCaseStmts[ID];
1927}
Douglas Gregor6e411bf2009-04-17 18:18:49 +00001928
1929/// \brief Record that the given label statement has been
1930/// deserialized and has the given ID.
1931void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
1932 assert(LabelStmts.find(ID) == LabelStmts.end() &&
1933 "Deserialized label twice");
1934 LabelStmts[ID] = S;
1935
1936 // If we've already seen any goto statements that point to this
1937 // label, resolve them now.
1938 typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
1939 std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
1940 for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
1941 Goto->second->setLabel(S);
1942 UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
Douglas Gregor95a8fe32009-04-17 18:58:21 +00001943
1944 // If we've already seen any address-label statements that point to
1945 // this label, resolve them now.
1946 typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
1947 std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
1948 = UnresolvedAddrLabelExprs.equal_range(ID);
1949 for (AddrLabelIter AddrLabel = AddrLabels.first;
1950 AddrLabel != AddrLabels.second; ++AddrLabel)
1951 AddrLabel->second->setLabel(S);
1952 UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
Douglas Gregor6e411bf2009-04-17 18:18:49 +00001953}
1954
1955/// \brief Set the label of the given statement to the label
1956/// identified by ID.
1957///
1958/// Depending on the order in which the label and other statements
1959/// referencing that label occur, this operation may complete
1960/// immediately (updating the statement) or it may queue the
1961/// statement to be back-patched later.
1962void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
1963 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
1964 if (Label != LabelStmts.end()) {
1965 // We've already seen this label, so set the label of the goto and
1966 // we're done.
1967 S->setLabel(Label->second);
1968 } else {
1969 // We haven't seen this label yet, so add this goto to the set of
1970 // unresolved goto statements.
1971 UnresolvedGotoStmts.insert(std::make_pair(ID, S));
1972 }
1973}
Douglas Gregor95a8fe32009-04-17 18:58:21 +00001974
1975/// \brief Set the label of the given expression to the label
1976/// identified by ID.
1977///
1978/// Depending on the order in which the label and other statements
1979/// referencing that label occur, this operation may complete
1980/// immediately (updating the statement) or it may queue the
1981/// statement to be back-patched later.
1982void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
1983 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
1984 if (Label != LabelStmts.end()) {
1985 // We've already seen this label, so set the label of the
1986 // label-address expression and we're done.
1987 S->setLabel(Label->second);
1988 } else {
1989 // We haven't seen this label yet, so add this label-address
1990 // expression to the set of unresolved label-address expressions.
1991 UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
1992 }
1993}