PTHLexer.cpp revision de7aeefc5573d669ed476d7bda7a8940d3bcadb7
1//===--- PTHLexer.cpp - Lex from a token stream ---------------------------===//
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 implements the PTHLexer interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/TokenKinds.h"
15#include "clang/Basic/FileManager.h"
16#include "clang/Basic/IdentifierTable.h"
17#include "clang/Lex/PTHLexer.h"
18#include "clang/Lex/Preprocessor.h"
19#include "clang/Lex/PTHManager.h"
20#include "clang/Lex/Token.h"
21#include "clang/Lex/Preprocessor.h"
22#include "llvm/ADT/StringMap.h"
23#include "llvm/ADT/OwningPtr.h"
24#include "llvm/Support/Compiler.h"
25#include "llvm/Support/MathExtras.h"
26#include "llvm/Support/MemoryBuffer.h"
27#include "llvm/System/Host.h"
28using namespace clang;
29
30#define DISK_TOKEN_SIZE (1+1+2+4+4)
31
32//===----------------------------------------------------------------------===//
33// Utility methods for reading from the mmap'ed PTH file.
34//===----------------------------------------------------------------------===//
35
36static inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) {
37  uint16_t V = ((uint16_t)Data[0] <<  0) |
38               ((uint16_t)Data[1] <<  8);
39  Data += 2;
40  return V;
41}
42
43static inline uint32_t ReadLE32(const unsigned char *&Data) {
44  // Hosts that directly support little-endian 32-bit loads can just
45  // use them.  Big-endian hosts need a bswap.
46  uint32_t V = *((uint32_t*)Data);
47  if (llvm::sys::isBigEndianHost())
48    V = llvm::ByteSwap_32(V);
49  Data += 4;
50  return V;
51}
52
53
54//===----------------------------------------------------------------------===//
55// PTHLexer methods.
56//===----------------------------------------------------------------------===//
57
58PTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const unsigned char *D,
59                   const unsigned char *ppcond,
60                   PTHSpellingSearch &mySpellingSrch, PTHManager &PM)
61  : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
62    PPCond(ppcond), CurPPCondPtr(ppcond), MySpellingSrch(mySpellingSrch),
63    PTHMgr(PM) {
64
65  FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID);
66}
67
68void PTHLexer::Lex(Token& Tok) {
69LexNextToken:
70
71  //===--------------------------------------==//
72  // Read the raw token data.
73  //===--------------------------------------==//
74
75  // Shadow CurPtr into an automatic variable.
76  const unsigned char *CurPtrShadow = CurPtr;
77
78  // Read in the data for the token.
79  unsigned Word0 = ReadLE32(CurPtrShadow);
80  uint32_t IdentifierID = ReadLE32(CurPtrShadow);
81  uint32_t FileOffset = ReadLE32(CurPtrShadow);
82
83  tok::TokenKind TKind = (tok::TokenKind) (Word0 & 0xFF);
84  Token::TokenFlags TFlags = (Token::TokenFlags) ((Word0 >> 8) & 0xFF);
85  uint32_t Len = Word0 >> 16;
86
87  CurPtr = CurPtrShadow;
88
89  //===--------------------------------------==//
90  // Construct the token itself.
91  //===--------------------------------------==//
92
93  Tok.startToken();
94  Tok.setKind(TKind);
95  Tok.setFlag(TFlags);
96  assert(!LexingRawMode);
97  Tok.setLocation(FileStartLoc.getFileLocWithOffset(FileOffset));
98  Tok.setLength(Len);
99
100  // Handle identifiers.
101  if (IdentifierID) {
102    MIOpt.ReadToken();
103    IdentifierInfo *II = PTHMgr.GetIdentifierInfo(IdentifierID-1);
104
105    Tok.setIdentifierInfo(II);
106
107    // Change the kind of this identifier to the appropriate token kind, e.g.
108    // turning "for" into a keyword.
109    Tok.setKind(II->getTokenID());
110
111    if (II->isHandleIdentifierCase())
112      PP->HandleIdentifier(Tok);
113    return;
114  }
115
116  //===--------------------------------------==//
117  // Process the token.
118  //===--------------------------------------==//
119#if 0
120  SourceManager& SM = PP->getSourceManager();
121  llvm::cerr << SM.getFileEntryForID(FileID)->getName()
122    << ':' << SM.getLogicalLineNumber(Tok.getLocation())
123    << ':' << SM.getLogicalColumnNumber(Tok.getLocation())
124    << '\n';
125#endif
126
127  if (TKind == tok::eof) {
128    // Save the end-of-file token.
129    EofToken = Tok;
130
131    Preprocessor *PPCache = PP;
132
133    assert(!ParsingPreprocessorDirective);
134    assert(!LexingRawMode);
135
136    // FIXME: Issue diagnostics similar to Lexer.
137    if (PP->HandleEndOfFile(Tok, false))
138      return;
139
140    assert(PPCache && "Raw buffer::LexEndOfFile should return a token");
141    return PPCache->Lex(Tok);
142  }
143
144  if (TKind == tok::hash && Tok.isAtStartOfLine()) {
145    LastHashTokPtr = CurPtr - DISK_TOKEN_SIZE;
146    assert(!LexingRawMode);
147    PP->HandleDirective(Tok);
148
149    if (PP->isCurrentLexer(this))
150      goto LexNextToken;
151
152    return PP->Lex(Tok);
153  }
154
155  if (TKind == tok::eom) {
156    assert(ParsingPreprocessorDirective);
157    ParsingPreprocessorDirective = false;
158    return;
159  }
160
161  MIOpt.ReadToken();
162}
163
164// FIXME: We can just grab the last token instead of storing a copy
165// into EofToken.
166void PTHLexer::getEOF(Token& Tok) {
167  assert(EofToken.is(tok::eof));
168  Tok = EofToken;
169}
170
171void PTHLexer::DiscardToEndOfLine() {
172  assert(ParsingPreprocessorDirective && ParsingFilename == false &&
173         "Must be in a preprocessing directive!");
174
175  // We assume that if the preprocessor wishes to discard to the end of
176  // the line that it also means to end the current preprocessor directive.
177  ParsingPreprocessorDirective = false;
178
179  // Skip tokens by only peeking at their token kind and the flags.
180  // We don't need to actually reconstruct full tokens from the token buffer.
181  // This saves some copies and it also reduces IdentifierInfo* lookup.
182  const unsigned char* p = CurPtr;
183  while (1) {
184    // Read the token kind.  Are we at the end of the file?
185    tok::TokenKind x = (tok::TokenKind) (uint8_t) *p;
186    if (x == tok::eof) break;
187
188    // Read the token flags.  Are we at the start of the next line?
189    Token::TokenFlags y = (Token::TokenFlags) (uint8_t) p[1];
190    if (y & Token::StartOfLine) break;
191
192    // Skip to the next token.
193    p += DISK_TOKEN_SIZE;
194  }
195
196  CurPtr = p;
197}
198
199/// SkipBlock - Used by Preprocessor to skip the current conditional block.
200bool PTHLexer::SkipBlock() {
201  assert(CurPPCondPtr && "No cached PP conditional information.");
202  assert(LastHashTokPtr && "No known '#' token.");
203
204  const unsigned char* HashEntryI = 0;
205  uint32_t Offset;
206  uint32_t TableIdx;
207
208  do {
209    // Read the token offset from the side-table.
210    Offset = ReadLE32(CurPPCondPtr);
211
212    // Read the target table index from the side-table.
213    TableIdx = ReadLE32(CurPPCondPtr);
214
215    // Compute the actual memory address of the '#' token data for this entry.
216    HashEntryI = TokBuf + Offset;
217
218    // Optmization: "Sibling jumping".  #if...#else...#endif blocks can
219    //  contain nested blocks.  In the side-table we can jump over these
220    //  nested blocks instead of doing a linear search if the next "sibling"
221    //  entry is not at a location greater than LastHashTokPtr.
222    if (HashEntryI < LastHashTokPtr && TableIdx) {
223      // In the side-table we are still at an entry for a '#' token that
224      // is earlier than the last one we saw.  Check if the location we would
225      // stride gets us closer.
226      const unsigned char* NextPPCondPtr =
227        PPCond + TableIdx*(sizeof(uint32_t)*2);
228      assert(NextPPCondPtr >= CurPPCondPtr);
229      // Read where we should jump to.
230      uint32_t TmpOffset = ReadLE32(NextPPCondPtr);
231      const unsigned char* HashEntryJ = TokBuf + TmpOffset;
232
233      if (HashEntryJ <= LastHashTokPtr) {
234        // Jump directly to the next entry in the side table.
235        HashEntryI = HashEntryJ;
236        Offset = TmpOffset;
237        TableIdx = ReadLE32(NextPPCondPtr);
238        CurPPCondPtr = NextPPCondPtr;
239      }
240    }
241  }
242  while (HashEntryI < LastHashTokPtr);
243  assert(HashEntryI == LastHashTokPtr && "No PP-cond entry found for '#'");
244  assert(TableIdx && "No jumping from #endifs.");
245
246  // Update our side-table iterator.
247  const unsigned char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2);
248  assert(NextPPCondPtr >= CurPPCondPtr);
249  CurPPCondPtr = NextPPCondPtr;
250
251  // Read where we should jump to.
252  HashEntryI = TokBuf + ReadLE32(NextPPCondPtr);
253  uint32_t NextIdx = ReadLE32(NextPPCondPtr);
254
255  // By construction NextIdx will be zero if this is a #endif.  This is useful
256  // to know to obviate lexing another token.
257  bool isEndif = NextIdx == 0;
258
259  // This case can occur when we see something like this:
260  //
261  //  #if ...
262  //   /* a comment or nothing */
263  //  #elif
264  //
265  // If we are skipping the first #if block it will be the case that CurPtr
266  // already points 'elif'.  Just return.
267
268  if (CurPtr > HashEntryI) {
269    assert(CurPtr == HashEntryI + DISK_TOKEN_SIZE);
270    // Did we reach a #endif?  If so, go ahead and consume that token as well.
271    if (isEndif)
272      CurPtr += DISK_TOKEN_SIZE*2;
273    else
274      LastHashTokPtr = HashEntryI;
275
276    return isEndif;
277  }
278
279  // Otherwise, we need to advance.  Update CurPtr to point to the '#' token.
280  CurPtr = HashEntryI;
281
282  // Update the location of the last observed '#'.  This is useful if we
283  // are skipping multiple blocks.
284  LastHashTokPtr = CurPtr;
285
286  // Skip the '#' token.
287  assert(((tok::TokenKind)*CurPtr) == tok::hash);
288  CurPtr += DISK_TOKEN_SIZE;
289
290  // Did we reach a #endif?  If so, go ahead and consume that token as well.
291  if (isEndif) { CurPtr += DISK_TOKEN_SIZE*2; }
292
293  return isEndif;
294}
295
296SourceLocation PTHLexer::getSourceLocation() {
297  // getSourceLocation is not on the hot path.  It is used to get the location
298  // of the next token when transitioning back to this lexer when done
299  // handling a #included file.  Just read the necessary data from the token
300  // data buffer to construct the SourceLocation object.
301  // NOTE: This is a virtual function; hence it is defined out-of-line.
302  const unsigned char *OffsetPtr = CurPtr + (DISK_TOKEN_SIZE - 4);
303  uint32_t Offset = ReadLE32(OffsetPtr);
304  return FileStartLoc.getFileLocWithOffset(Offset);
305}
306
307//===----------------------------------------------------------------------===//
308// getSpelling() - Use cached data in PTH files for getSpelling().
309//===----------------------------------------------------------------------===//
310
311unsigned PTHManager::getSpelling(FileID FID, unsigned FPos,
312                                 const char *&Buffer) {
313  llvm::DenseMap<FileID, PTHSpellingSearch*>::iterator I =SpellingMap.find(FID);
314
315  if (I == SpellingMap.end())
316    return 0;
317
318  return I->second->getSpellingBinarySearch(FPos, Buffer);
319}
320
321unsigned PTHManager::getSpelling(SourceLocation Loc, const char *&Buffer) {
322  SourceManager &SM = PP->getSourceManager();
323  Loc = SM.getSpellingLoc(Loc);
324  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
325  return getSpelling(LocInfo.first, LocInfo.second, Buffer);
326}
327
328unsigned PTHManager::getSpellingAtPTHOffset(unsigned PTHOffset,
329                                            const char *&Buffer) {
330  assert(PTHOffset < Buf->getBufferSize());
331  const unsigned char* Ptr =
332    (const unsigned char*)Buf->getBufferStart() + PTHOffset;
333
334  // The string is prefixed by 16 bits for its length, followed by the string
335  // itself.
336  unsigned Len = ReadUnalignedLE16(Ptr);
337  Buffer = (const char *)Ptr;
338  return Len;
339}
340
341unsigned PTHSpellingSearch::getSpellingLinearSearch(unsigned FPos,
342                                                    const char *&Buffer) {
343  const unsigned char *Ptr = LinearItr;
344  unsigned Len = 0;
345
346  if (Ptr == TableEnd)
347    return getSpellingBinarySearch(FPos, Buffer);
348
349  do {
350    uint32_t TokOffset = ReadLE32(Ptr);
351
352    if (TokOffset > FPos)
353      return getSpellingBinarySearch(FPos, Buffer);
354
355    // Did we find a matching token offset for this spelling?
356    if (TokOffset == FPos) {
357      uint32_t SpellingPTHOffset = ReadLE32(Ptr);
358      Len = PTHMgr.getSpellingAtPTHOffset(SpellingPTHOffset, Buffer);
359      break;
360    }
361  } while (Ptr != TableEnd);
362
363  LinearItr = Ptr;
364  return Len;
365}
366
367
368unsigned PTHSpellingSearch::getSpellingBinarySearch(unsigned FPos,
369                                                    const char *&Buffer) {
370
371  assert((TableEnd - TableBeg) % SpellingEntrySize == 0);
372  assert(TableEnd >= TableBeg);
373
374  if (TableEnd == TableBeg)
375    return 0;
376
377  unsigned min = 0;
378  const unsigned char *tb = TableBeg;
379  unsigned max = NumSpellings;
380
381  do {
382    unsigned i = (max - min) / 2 + min;
383    const unsigned char *Ptr = tb + (i * SpellingEntrySize);
384
385    uint32_t TokOffset = ReadLE32(Ptr);
386    if (TokOffset > FPos) {
387      max = i;
388      assert(!(max == min) || (min == i));
389      continue;
390    }
391
392    if (TokOffset < FPos) {
393      if (i == min)
394        break;
395
396      min = i;
397      continue;
398    }
399
400    uint32_t SpellingPTHOffset = ReadLE32(Ptr);
401    return PTHMgr.getSpellingAtPTHOffset(SpellingPTHOffset, Buffer);
402  }
403  while (min != max);
404
405  return 0;
406}
407
408unsigned PTHLexer::getSpelling(SourceLocation Loc, const char *&Buffer) {
409  SourceManager &SM = PP->getSourceManager();
410  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedSpellingLoc(Loc);
411
412  FileID FID = LocInfo.first;
413  unsigned FPos = LocInfo.second;
414
415  if (FID == getFileID())
416    return MySpellingSrch.getSpellingLinearSearch(FPos, Buffer);
417  return PTHMgr.getSpelling(FID, FPos, Buffer);
418}
419
420//===----------------------------------------------------------------------===//
421// Internal Data Structures for PTH file lookup and resolving identifiers.
422//===----------------------------------------------------------------------===//
423
424
425/// PTHFileLookup - This internal data structure is used by the PTHManager
426///  to map from FileEntry objects managed by FileManager to offsets within
427///  the PTH file.
428namespace {
429class VISIBILITY_HIDDEN PTHFileLookup {
430public:
431  class Val {
432    uint32_t TokenOff;
433    uint32_t PPCondOff;
434    uint32_t SpellingOff;
435  public:
436    Val() : TokenOff(~0) {}
437    Val(uint32_t toff, uint32_t poff, uint32_t soff)
438      : TokenOff(toff), PPCondOff(poff), SpellingOff(soff) {}
439
440    bool isValid() const { return TokenOff != ~((uint32_t)0); }
441
442    uint32_t getTokenOffset() const {
443      assert(isValid() && "PTHFileLookup entry initialized.");
444      return TokenOff;
445    }
446
447    uint32_t getPPCondOffset() const {
448      assert(isValid() && "PTHFileLookup entry initialized.");
449      return PPCondOff;
450    }
451
452    uint32_t getSpellingOffset() const {
453      assert(isValid() && "PTHFileLookup entry initialized.");
454      return SpellingOff;
455    }
456  };
457
458private:
459  llvm::StringMap<Val> FileMap;
460
461public:
462  PTHFileLookup() {};
463
464  bool isEmpty() const {
465    return FileMap.empty();
466  }
467
468  Val Lookup(const FileEntry* FE) {
469    const char* s = FE->getName();
470    unsigned size = strlen(s);
471    return FileMap.GetOrCreateValue(s, s+size).getValue();
472  }
473
474  void ReadTable(const unsigned char* D) {
475    uint32_t N = ReadLE32(D);     // Read the length of the table.
476
477    for ( ; N > 0; --N) {       // The rest of the data is the table itself.
478      uint32_t Len = ReadLE32(D);
479      const char* s = (const char *)D;
480      D += Len;
481
482      uint32_t TokenOff = ReadLE32(D);
483      uint32_t PPCondOff = ReadLE32(D);
484      uint32_t SpellingOff = ReadLE32(D);
485
486      FileMap.GetOrCreateValue(s, s+Len).getValue() =
487        Val(TokenOff, PPCondOff, SpellingOff);
488    }
489  }
490};
491} // end anonymous namespace
492
493//===----------------------------------------------------------------------===//
494// PTHManager methods.
495//===----------------------------------------------------------------------===//
496
497PTHManager::PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup,
498                       const unsigned char* idDataTable,
499                       IdentifierInfo** perIDCache,
500                       const unsigned char* sortedIdTable, unsigned numIds)
501: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup),
502  IdDataTable(idDataTable), SortedIdTable(sortedIdTable),
503  NumIds(numIds), PP(0) {}
504
505PTHManager::~PTHManager() {
506  delete Buf;
507  delete (PTHFileLookup*) FileLookup;
508  free(PerIDCache);
509}
510
511PTHManager* PTHManager::Create(const std::string& file) {
512  // Memory map the PTH file.
513  llvm::OwningPtr<llvm::MemoryBuffer>
514  File(llvm::MemoryBuffer::getFile(file.c_str()));
515
516  if (!File)
517    return 0;
518
519  // Get the buffer ranges and check if there are at least three 32-bit
520  // words at the end of the file.
521  const unsigned char* BufBeg = (unsigned char*)File->getBufferStart();
522  const unsigned char* BufEnd = (unsigned char*)File->getBufferEnd();
523
524  if(!(BufEnd > BufBeg + sizeof(uint32_t)*3)) {
525    assert(false && "Invalid PTH file.");
526    return 0; // FIXME: Proper error diagnostic?
527  }
528
529  // Compute the address of the index table at the end of the PTH file.
530  // This table contains the offset of the file lookup table, the
531  // persistent ID -> identifer data table.
532  // FIXME: We should just embed this offset in the PTH file.
533  const unsigned char* EndTable = BufEnd - sizeof(uint32_t)*4;
534
535  // Construct the file lookup table.  This will be used for mapping from
536  // FileEntry*'s to cached tokens.
537  const unsigned char* FileTableOffset = EndTable + sizeof(uint32_t)*3;
538  const unsigned char* FileTable = BufBeg + ReadLE32(FileTableOffset);
539
540  if (!(FileTable > BufBeg && FileTable < BufEnd)) {
541    assert(false && "Invalid PTH file.");
542    return 0; // FIXME: Proper error diagnostic?
543  }
544
545  llvm::OwningPtr<PTHFileLookup> FL(new PTHFileLookup());
546  FL->ReadTable(FileTable);
547
548  if (FL->isEmpty())
549    return 0;
550
551  // Get the location of the table mapping from persistent ids to the
552  // data needed to reconstruct identifiers.
553  const unsigned char* IDTableOffset = EndTable + sizeof(uint32_t)*1;
554  const unsigned char* IData = BufBeg + ReadLE32(IDTableOffset);
555
556  if (!(IData >= BufBeg && IData < BufEnd)) {
557    assert(false && "Invalid PTH file.");
558    return 0; // FIXME: Proper error diagnostic?
559  }
560
561  // Get the location of the lexigraphically-sorted table of persistent IDs.
562  const unsigned char* SortedIdTableOffset = EndTable + sizeof(uint32_t)*2;
563  const unsigned char* SortedIdTable = BufBeg + ReadLE32(SortedIdTableOffset);
564  if (!(SortedIdTable >= BufBeg && SortedIdTable < BufEnd)) {
565    assert(false && "Invalid PTH file.");
566    return 0; // FIXME: Proper error diagnostic?
567  }
568
569  // Get the number of IdentifierInfos and pre-allocate the identifier cache.
570  uint32_t NumIds = ReadLE32(IData);
571
572  // Pre-allocate the peristent ID -> IdentifierInfo* cache.  We use calloc()
573  // so that we in the best case only zero out memory once when the OS returns
574  // us new pages.
575  IdentifierInfo** PerIDCache = 0;
576
577  if (NumIds) {
578    PerIDCache = (IdentifierInfo**)calloc(NumIds, sizeof(*PerIDCache));
579    if (!PerIDCache) {
580      assert(false && "Could not allocate Persistent ID cache.");
581      return 0;
582    }
583  }
584
585  // Create the new PTHManager.
586  return new PTHManager(File.take(), FL.take(), IData, PerIDCache,
587                        SortedIdTable, NumIds);
588}
589IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {
590  // Look in the PTH file for the string data for the IdentifierInfo object.
591  const unsigned char* TableEntry = IdDataTable + sizeof(uint32_t)*PersistentID;
592  const unsigned char* IDData =
593    (const unsigned char*)Buf->getBufferStart() + ReadLE32(TableEntry);
594  assert(IDData < (const unsigned char*)Buf->getBufferEnd());
595
596  // Allocate the object.
597  std::pair<IdentifierInfo,const unsigned char*> *Mem =
598    Alloc.Allocate<std::pair<IdentifierInfo,const unsigned char*> >();
599
600  Mem->second = IDData;
601  IdentifierInfo *II = new ((void*) Mem) IdentifierInfo();
602
603  // Store the new IdentifierInfo in the cache.
604  PerIDCache[PersistentID] = II;
605  return II;
606}
607
608IdentifierInfo* PTHManager::get(const char *NameStart, const char *NameEnd) {
609  unsigned min = 0;
610  unsigned max = NumIds;
611  unsigned Len = NameEnd - NameStart;
612
613  do {
614    unsigned i = (max - min) / 2 + min;
615    const unsigned char *Ptr = SortedIdTable + (i * 4);
616
617    // Read the persistentID.
618    unsigned perID = ReadLE32(Ptr);
619
620    // Get the IdentifierInfo.
621    IdentifierInfo* II = GetIdentifierInfo(perID);
622
623    // First compare the lengths.
624    unsigned IILen = II->getLength();
625    if (Len < IILen) goto IsLess;
626    if (Len > IILen) goto IsGreater;
627
628    // Now compare the strings!
629    {
630      signed comp = strncmp(NameStart, II->getName(), Len);
631      if (comp < 0) goto IsLess;
632      if (comp > 0) goto IsGreater;
633    }
634    // We found a match!
635    return II;
636
637  IsGreater:
638    if (i == min) break;
639    min = i;
640    continue;
641
642  IsLess:
643    max = i;
644    assert(!(max == min) || (min == i));
645  }
646  while (min != max);
647
648  return 0;
649}
650
651
652PTHLexer *PTHManager::CreateLexer(FileID FID) {
653  const FileEntry *FE = PP->getSourceManager().getFileEntryForID(FID);
654  if (!FE)
655    return 0;
656
657  // Lookup the FileEntry object in our file lookup data structure.  It will
658  // return a variant that indicates whether or not there is an offset within
659  // the PTH file that contains cached tokens.
660  PTHFileLookup::Val FileData = ((PTHFileLookup*)FileLookup)->Lookup(FE);
661
662  if (!FileData.isValid()) // No tokens available.
663    return 0;
664
665  const unsigned char *BufStart = (const unsigned char *)Buf->getBufferStart();
666  // Compute the offset of the token data within the buffer.
667  const unsigned char* data = BufStart + FileData.getTokenOffset();
668
669  // Get the location of pp-conditional table.
670  const unsigned char* ppcond = BufStart + FileData.getPPCondOffset();
671  uint32_t Len = ReadLE32(ppcond);
672  if (Len == 0) ppcond = 0;
673
674  // Get the location of the spelling table.
675  const unsigned char* spellingTable = BufStart + FileData.getSpellingOffset();
676
677  Len = ReadLE32(spellingTable);
678  if (Len == 0) spellingTable = 0;
679
680  assert(data < (const unsigned char*)Buf->getBufferEnd());
681
682  // Create the SpellingSearch object for this FileID.
683  PTHSpellingSearch* ss = new PTHSpellingSearch(*this, Len, spellingTable);
684  SpellingMap[FID] = ss;
685
686  assert(PP && "No preprocessor set yet!");
687  return new PTHLexer(*PP, FID, data, ppcond, *ss, *this);
688}
689