PTH: Hook up getSpelling() caching in PTHLexer. This results in a nice
performance gain. Here's what we see for -Eonly on Cocoa.h (using PTH):

- wall time decreases by 21% (26% speedup overall)
- system time decreases by 35%
- user time decreases by 6%

These reductions are due to not paging source files just to get spellings for
literals. The solution in place doesn't appear to be 100% yet, as we still see
some of the pages for source files getting mapped in. Using -print-stats, we see
that SourceManager maps in 7179K less bytes of source text (reduction of 75%).
Will investigate why the remaining 25% are getting paged in.

With these changes, here's how PTH compares to non-PTH on Cocoa.h:
  -Eonly: PTH takes 64% of the time as non-PTH (54% speedup)
  -fsyntax-only: PTH takes 89% of the time as non-PTH (11% speedup)


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61913 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index ef7cfb1..cfd5c64 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/lib/Lex/PTHLexer.cpp
@@ -49,9 +49,13 @@
 //===----------------------------------------------------------------------===//
 
 PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D,
-                   const char* ppcond, PTHManager& PM)
+                   const char* ppcond,
+                   const char* spellingTable, unsigned NumSpellings,
+                   PTHManager& PM)
   : PreprocessorLexer(&pp, fileloc), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
-    PPCond(ppcond), CurPPCondPtr(ppcond), PTHMgr(PM) {}
+    PPCond(ppcond), CurPPCondPtr(ppcond), 
+    SpellingTable(spellingTable), SpellingsLeft(NumSpellings),
+    PTHMgr(PM) {}
 
 void PTHLexer::Lex(Token& Tok) {
 LexNextToken:
@@ -285,8 +289,55 @@
   return SourceLocation::getFileLoc(FileID, offset);
 }
 
+unsigned PTHManager::GetSpelling(unsigned PTHOffset, const char *& Buffer) {
+  const char* p = Buf->getBufferStart() + PTHOffset;
+  assert(p < Buf->getBufferEnd());
+  
+  // The string is prefixed by 16 bits for its length, followed by the string
+  // itself.
+  unsigned len = ((unsigned) ((uint8_t) p[0]))
+    | (((unsigned) ((uint8_t) p[1])) << 8);
+
+  Buffer = p + 2;
+  return len;
+}
+
 unsigned PTHLexer::getSpelling(SourceLocation sloc, const char *&Buffer) {
-  return 0;
+  const char* p = SpellingTable;
+  SourceManager& SM = PP->getSourceManager();
+  unsigned fpos = SM.getFullFilePos(SM.getPhysicalLoc(sloc));
+  unsigned len = 0;
+
+  while (SpellingsLeft) {
+    uint32_t TokOffset = 
+      ((uint32_t) ((uint8_t) p[0]))
+      | (((uint32_t) ((uint8_t) p[1])) << 8)
+      | (((uint32_t) ((uint8_t) p[2])) << 16)
+      | (((uint32_t) ((uint8_t) p[3])) << 24);
+    
+    if (TokOffset > fpos)
+      break;
+    
+    --SpellingsLeft;
+    
+    // Did we find a matching token offset for this spelling?
+    if (TokOffset == fpos) {
+      uint32_t SpellingPTHOffset = 
+        ((uint32_t) ((uint8_t) p[4]))
+        | (((uint32_t) ((uint8_t) p[5])) << 8)
+        | (((uint32_t) ((uint8_t) p[6])) << 16)
+        | (((uint32_t) ((uint8_t) p[7])) << 24);
+      
+      len = PTHMgr.GetSpelling(SpellingPTHOffset, Buffer);
+      break;
+    }
+
+    // No match.  Keep on looking.
+    p += sizeof(uint32_t)*2;
+  }
+
+  SpellingTable = p;
+  return len;
 }
 
 //===----------------------------------------------------------------------===//
@@ -478,8 +529,15 @@
   const char* ppcond = Buf->getBufferStart() + FileData.getPPCondOffset();
   uint32_t len = Read32(ppcond);
   if (len == 0) ppcond = 0;
+  
+  // Get the location of the spelling table.
+  const char* spellingTable = Buf->getBufferStart() +
+                              FileData.getSpellingOffset();
+  
+  len = Read32(spellingTable);
+  if (len == 0) spellingTable = 0;
 
   assert(data < Buf->getBufferEnd());
   return new PTHLexer(PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond,
-                      *this); 
+                      spellingTable, len, *this); 
 }